├── .elpaignore ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── config.yml ├── .gitignore ├── CHANGELOG.org ├── LICENSE ├── README.org ├── consult-compile.el ├── consult-flymake.el ├── consult-imenu.el ├── consult-info.el ├── consult-kmacro.el ├── consult-org.el ├── consult-register.el ├── consult-xref.el └── consult.el /.elpaignore: -------------------------------------------------------------------------------- 1 | LICENSE 2 | .elpaignore 3 | .github -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | name: 🐞 Bug report 4 | about: Report a bug. Do not use this for questions, support or feature requests. 5 | --- 6 | Thank you for reporting a bug. 7 | 8 | Please start with `emacs -Q` or `package-isolate` in order to only load a 9 | minimal set of packages. This way your Emacs configuration is not loaded. 10 | 11 | Please provide precise information and the exact steps to reproduce the issue. 12 | This is important to ensure that your problem can be reproduced on a different 13 | machine. 14 | 15 | If you are not really sure if your issue is a bug, please open a discussion 16 | instead. 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: "🙏 Please support my work on Consult and my other Emacs packages" 4 | url: https://github.com/sponsors/minad 5 | about: Thanks! Your support helps dedicating time to project maintenance and development. 6 | - name: "💡 Suggest a feature ➞ Please create a discussion" 7 | url: https://github.com/minad/consult/discussions/categories/ideas 8 | about: Start a new discussion suggesting an improvement or a feature. 9 | - name: "🧑‍🤝‍🧑 Ask the community for support" 10 | url: https://www.reddit.com/r/emacs 11 | about: Please be kind and support others. 12 | - name: "🤓 Ask the maintainer for support ➞ Please create a discussion" 13 | url: https://github.com/minad/consult/discussions/categories/q-a 14 | about: Please keep in mind that my bandwidth is limited. 15 | - name: "🔍 Search through old issues or discussions" 16 | url: https://github.com/search?q=repo%3Aminad%2Fconsult&type=issues 17 | about: The same question may have been asked before. 18 | - name: "📝 Consult wiki" 19 | url: https://github.com/minad/consult/wiki 20 | about: Additional configuration tips are covered there. Feel free to edit! 21 | - name: "📖 Consult manual" 22 | url: https://github.com/minad/consult/blob/main/README.org 23 | about: The manual covers the basic setup and workflow. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-autoloads.el 2 | *-pkg.el 3 | *.elc 4 | *.info 5 | *.texi 6 | *~ 7 | \#*\# 8 | /README-elpa 9 | -------------------------------------------------------------------------------- /CHANGELOG.org: -------------------------------------------------------------------------------- 1 | #+title: consult.el - Changelog 2 | #+author: Daniel Mendler 3 | #+language: en 4 | 5 | * Development 6 | 7 | - ~consult--source-buffer-register~: New source for buffer registers. 8 | - ~consult-compile-error~: Add prefix argument to jump to error message in the 9 | compilation buffer instead of error location. 10 | 11 | * Version 2.4 (2025-05-21) 12 | 13 | - ~consult-register-store~: Add =M-b= action to store the buffer in a register. 14 | - ~consult-compile~: Ignore messages without a location. 15 | - ~consult-compile~: Introduce key =g= for grep locations. 16 | 17 | * Version 2.3 (2025-04-19) 18 | 19 | - Bugfix: ~consult--read~ accepts list of symbols. 20 | - Bugfix: ~consult-theme~ handles invalid themes gracefully. 21 | 22 | * Version 2.2 (2025-04-02) 23 | 24 | - Add ~consult-info-define~ to conveniently define custom ~consult-info-*~ commands 25 | to search through a subset of info manuals. 26 | - ~consult-focus-lines~: Add mode line indicator if active. 27 | - ~consult-grep~: Preserve empty context lines. 28 | - ~consult-register-store~: Support Dired buffers. 29 | 30 | * Version 2.1 (2025-03-11) 31 | 32 | - Remove obsolete ~consult--async-*~ APIs. 33 | - File preview: Ensure that remote files do not slow down preview. 34 | - File preview: Do not preview gpg files. 35 | - ~consult-yank-pop~, ~consult-history~: Respect display properties when previewing 36 | to avoid leaking hidden data. 37 | - ~consult-completion-in-region~: Auto-detect completion UI. 38 | - ~consult-completion-in-region~: Improve handling of single candidates. 39 | 40 | * Version 2.0 (2025-01-28) 41 | 42 | - New features: 43 | + ~consult--multi~: Add support for asynchronous sources. 44 | + ~consult-man~: Add preview. 45 | - *BREAKING CHANGE*: New async API 46 | + Async functions must have the uniform curried form 47 | ~(lambda (sink) (lambda (action) ...)~ and are composed with 48 | ~consult--async-pipeline~. See the docstring of ~consult--async-pipeline~ for 49 | details. 50 | + ~consult--read~: New ~:async-wrap~ keyword argument. 51 | + ~consult--multi~: Add support for ~:async~ sources. 52 | + ~consult--async-min-input~: New async function which enforces a minimum input 53 | length. The input length check has been removed from ~consult--async-split~. 54 | + ~consult--async-transform~: Macro converted to function. 55 | + ~consult--process-collection~: New function replacing ~consult--async-command~. 56 | The function accepts keyword arguments to customize the pipeline. 57 | + ~consult--dynamic-collection~: The function accepts more keyword arguments to 58 | customize the pipeline. 59 | + ~consult--async-refresh-timer~ and ~consult--async-refresh-immediate~: Replaced by 60 | ~consult--async-refresh~ with a ~DELAY~ argument. 61 | + ~consult--async-split-thingatpt~ and ~consult--async-split-initial~: Removed 62 | since ~consult--read~ automatically inserts the splitter prefix if needed. 63 | - Minor changes: 64 | + Remove obsolete ~consult-yank-rotate~. 65 | + Add customizable variable ~consult-async-indicator~. 66 | + ~consult-completion-in-region~: When inside minibuffer, use minibuffer content 67 | as prompt. 68 | 69 | * Version 1.9 (2024-12-22) 70 | 71 | - Require Emacs 28.1. 72 | - ~consult-grep~, ~consult-find~ and similar commands: Ask for project first, when 73 | invoked with double prefix argument ~C-u C-u~. 74 | - Deprecate ~consult-yank-rotate~ in favor of ~yank-from-kill-ring-rotate~. 75 | - ~consult-grep-max-columns~: Support value ~nil~ to disable truncation. 76 | - ~consult-line~: Enforce global completion style settings for compatibility with 77 | buffer-local completion style settings, which may be used by Corfu. 78 | - Support the value 0 for ~consult-async-min-input~. 79 | - Remove special ~org-fold~ code. Set ~org-fold-core-style~ to ~overlays~ if unfolding 80 | in Org files does not work for you. 81 | - ~consult-info~: Support sub files. 82 | - ~consult-buffer~, ~consult-project-buffer~: Add sources for known project roots. 83 | - ~consult--multi~: Support multiple narrow keys per source. Used by the project 84 | buffer and project recent file source. 85 | - ~consult--async-sink~: The new action ~cancel~ was added to the async protocol. 86 | - ~consult--read~: Add new keyword argument ~:initial-narrow~. 87 | 88 | * Version 1.8 (2024-07-25) 89 | 90 | - =consult-preview-excluded-buffers=: New customization variable. 91 | - =consult-fd=: Support multiple paths. 92 | - Bump Compat dependency to Compat 30. 93 | 94 | * Version 1.7 (2024-05-23) 95 | 96 | - Emacs 30 bug fix: Ensure that font locking is enabled when previewing files. 97 | - ~consult-preview-allowed-hooks~: Global minor modes, which should be enabled 98 | during preview, can be added to this list. See the README for examples. 99 | - ~consult-xref~: Bug fix: Do not error when project root directory is nil. 100 | - ~consult-fd~: Bug fix: Avoid confusion of input pattern with options by 101 | prefixing the input pattern with ~--and~. 102 | - ~consult--buffer-sort-visibility~: Bug fix: Only add current buffer to sorted 103 | list, if already present in the original list. 104 | 105 | * Version 1.6 (2024-05-15) 106 | 107 | - ~consult-xref~: Compatibility with xref.el in Emacs 30. 108 | - ~consult-grep~ (and similar): Preserve files which are already open literally 109 | and do not reopen them in normal mode. 110 | - ~consult-preview-allowed-hooks~: Run delayed mode hooks listed in this variable 111 | during preview. 112 | - ~consult--buffer-query~: Add buffer-list keyword argument. 113 | 114 | * Version 1.5 (2024-04-19) 115 | 116 | - Bugfix ~consult-buffer~: Handle buffer renaming during minibuffer completion 117 | gracefully, by attaching the actual buffer objects to the completion candidate 118 | strings. 119 | - Bugfix ~consult-register~: Ignore marker registers pointing to dead buffers. 120 | 121 | * Version 1.4 (2024-03-08) 122 | 123 | - Bugfix: File preview: Ensure that binary files are not previewed partially. 124 | Otherwise ~pdf-view-mode~ may observe corrupted PDF files. 125 | - ~consult--async-refresh-timer~: Optimize timer reuse and efficiency. This change 126 | improves the performance of commands like ~consult-ripgrep~ for small values of 127 | ~consult-async-refresh-delay~. 128 | - ~consult-completion-in-region~: Remove ~:cycle-threshold~ and ~:completion-styles~ 129 | customization options. 130 | 131 | * Version 1.3 (2024-02-23) 132 | 133 | - ~consult-bookmark-narrow~: More flexible grouping which supports multiple 134 | bookmark handlers per group. 135 | - Bugfix: Ensure that preview is always executed in a non-minibuffer window. 136 | - Bugfix: File preview: Do not preview ~hexl-mode~ buffers. 137 | - Bugfix: File preview: use ~error-message-string~ to access error string. 138 | - Bugfix: Buffer preview: Retrieve original window correctly. 139 | - Bugfix: Fix ~consult-global-mark~ for ~embark-export~. 140 | 141 | * Version 1.2 (2024-01-23) 142 | 143 | - =consult-buffer=: Bugfix. Ensure that null completion works properly. 144 | - File preview: Add indication if previewed file got truncated. 145 | 146 | * Version 1.1 (2023-12-27) 147 | 148 | - Bugfixes: 149 | + ~consult-xref~: Do not error for an empty location list. 150 | + ~consult--read~: Catch null completion if require-match is non-nil. 151 | + ~consult--multi~: Ensure that :new action is invoked on visible source. 152 | - File preview: Check for long lines when previewing files partially. 153 | - Use ~minibuffer-local-filename-syntax~ and ~read-file-name-completion-ignore-case~ 154 | for directory prompt of the ~consult-grep~ and ~consult--find~ family of commands. 155 | - Remove obsolete variables ~consult-preview-max-size~ and 156 | ~consult-preview-raw-size~. 157 | 158 | * Version 1.0 (2023-12-01) 159 | 160 | - Bugfixes. 161 | - Preview large files partially. Add new customization variables 162 | =consult-preview-partial-chunk= and =consult-preview-partial-limit=. This new 163 | feature is experimental. Please report any issues you observe. 164 | - Obsoleted =consult-preview-max-size= and =consult-preview-raw-size=. 165 | - =consult-buffer-other-tab=: New command. 166 | - =consult-fd=: New command based on the fast =fd/fdfind= search utility. 167 | - =consult-outline=: New prefix argument to specify initial narrowing level. 168 | - =consult-org-heading=: Specify category =org-heading= such that Embark provides 169 | appropriate Org heading actions. 170 | - =consult-org-heading=: Add annotation. 171 | - =consult-locate=: Split input into multiple words. 172 | - Remove unreliable =consult--maybe-recenter=. 173 | - Save input history even when using =embark-export= or when aborting from a 174 | command via C-g. This change affects commands like =consult-line= and 175 | =consult-grep=. 176 | - Unify history of =consult-line=, =consult-keep-lines= and =consult-focus-lines=. 177 | 178 | * Version 0.35 (2023-07-02) 179 | 180 | - Bugfixes. 181 | - =consult--read= now accepts programmable completion tables as argument, e.g., 182 | =completion-table-dynamic= or =completion--file-name-table=. This allows you to 183 | reuse existing completion tables to write completion commands enhanced with 184 | Consult candidate preview. 185 | - Replace =consult-preview-cursor= face with =cursor-highlight-mark=. 186 | - Change calling convention of =consult-focus-lines= and =consult-keep-lines=. 187 | - The regexps in =consult-buffer-filter= are matched case sensitively now. 188 | Similarly, the =INCLUDE= and =EXCLUDE= arguments of =consult--buffer-query= are also 189 | case sensitive. 190 | - Do not preview remote files by default, see =consult-preview-excluded-files=. 191 | - Use =consult--maybe-recenter= instead of =recenter= in =consult-after-jump-hook=. 192 | - =consult-goto-line=: Support =line:column= input. 193 | 194 | * Version 0.34 (2023-04-21) 195 | 196 | - Bugfixes. 197 | - =consult-org-heading=: Support tag inheritance. 198 | - Use pure =consult--fast-abbreviate-file-name= function to abbreviate file names 199 | in =consult-buffer= and =consult-recent-file=. This ensures that abbreviation does 200 | not access the file system (or worse remote hosts via Tramp) and is always 201 | fast. The downside is that some paths may not get abbreviated. 202 | - Introduce buffer sources =consult--source-project-buffer-hidden= and 203 | =consult--source-project-recent-file-hidden=. Set the buffer sources of 204 | =consult-project= to =consult--source-project-buffer= and 205 | =consult--source-project-recent-file= to ease customization. 206 | - =consult-buffer=: Explicitly save =window-next-buffers= and =window-prev-buffers=. 207 | - When previewing files literally (=consult-preview-raw-size=), set the multi byte 208 | flag of the previewed buffer, such that UTF-8 buffers are not garbled. 209 | - Do not create preview cursor overlay. Instead display the actual point by 210 | ensuring that =cursor-in-non-selected-windows= is set. 211 | 212 | * Version 0.33 (2023-03-11) 213 | 214 | - BREAKING: The key convention has been updated. The old key convention is not 215 | supported anymore. Keys must now be strings valid according to =key-valid-p=. 216 | This changes affects the keys =consult-narrow-key=, =consult-widen-key=, 217 | =consult-preview-key= and the =:preview-key= of sources and passed as keyword 218 | argument to =consult--read=. See the example configurations in the manual. 219 | - BREAKING: Remove the "." argument from =consult-grep-args= and 220 | =consult-ripgrep-args=, since directories or files to search are appended by the 221 | command line builder. Take this change into account, when you use a customized 222 | version of those variables. 223 | - =consult-grep=: Add support for grep and find over multiple files or directory. 224 | If the prefix argument DIR is a single C-u, prompt for comma separated 225 | directories or files to search recursively via =completing-read-multiple=. 226 | - =consult-buffer= and =consult-isearch-history=: Align annotations dynamically 227 | depending on candidate width, instead of computing the alignment beforehand. 228 | - Add the full path as =help-echo= property to abbreviated directory paths and 229 | project names. Enable =tooltip-mode= and hover with the mouse over the 230 | abbreviated directory path to see the full path. 231 | - =consult-grep/find/etc=: Print first line of stderr output if command failed. 232 | 233 | * Version 0.32 (2023-02-06) 234 | 235 | - Bugfixes 236 | - Deprecate the old key convention. Keys must now be strings valid according to 237 | =key-valid-p=. This changes affects the keys =consult-narrow-key=, 238 | =consult-widen-key=, =consult-preview-key= and the =:preview-key= of sources and 239 | passed as keyword argument to =consult--read=. See the example configurations in 240 | the manual. 241 | - Add =consult-info= command (#634, #727). 242 | - =consult-buffer=: Always select the first candidate when narrowing (#714). 243 | - =consult-locate-args=: Remove =--existing=, which is not supported by =plocate= on 244 | Debian stable. 245 | - =consult-ripgrep-args=: Add =--search-zip= option to automatically search through 246 | compressed files. This will allow you to search Elisp files bundled with your 247 | Emacs installation. Move to an Elisp library via =find-library=, then invoke 248 | =consult-ripgrep=. 249 | - Drop obsolete =consult-apropos=. Alternatives: =describe-symbol= in combination 250 | with =embark-export=. See also =consult-info= and =consult-ripgrep= to search 251 | through info manuals and Elisp source code. 252 | - Drop obsolete =consult-multi-occur=. Alternative: Built-in =multi-occur=, 253 | =multi-occur-in-matching-buffers= or =consult-line-multi=. 254 | - Drop obsolete =consult-file-externally=. The command has been moved to Embark 255 | under the name =embark-open-externally=. 256 | 257 | * Version 0.31 (2023-01-06) 258 | 259 | - Version bump to update the Compat package dependency (29.1.0.1) 260 | 261 | * Version 0.30 (2023-01-02) 262 | 263 | - Bugfixes 264 | - Drop Selectrum support 265 | - Deprecate =consult-file-externally= in favor of =embark-open-externally= 266 | - Deprecate =consult-multi-occur=. The =multi-occur= command should be improved 267 | upstream to take advantage of =completing-read-multiple=. Consult provides the 268 | command =consult-line-multi= as an alternative. 269 | - =consult-history=: Use input as initial completion input 270 | 271 | * Version 0.29 (2022-12-03) 272 | 273 | - Bugfixes 274 | - =consult-line-multi= has been rewritten completely. The candidates are computed 275 | on demand based on the input. This reduces startup speed greatly. The command 276 | behaves like =consult-grep=, but operates on buffers instead of files. 277 | - Add =consult--source-file-register=, and make the registers available in 278 | =consult-buffer=. Registers are often used as quick access keys for files, e.g., 279 | =(add-to-list 'register-alist '(?i file . "~/.emacs.d/init.el")))=. 280 | - Remove obsolete =consult-line-point-placement= 281 | - =consult-grep/find=: Always show directory in the prompt 282 | - Add variable =consult-yank-rotate=, =consult-yank-from-kill-ring= rotates kill ring 283 | - Emacs 29: =consult-register= supports =buffer= register type 284 | - Emacs 29: Support =outline-search-function= 285 | - Org 9.6: Support new =org-fold-core= API (both overlays and text-properties) 286 | - Support abbreviated file names in =recentf-list=, see =recentf-filename-handler=. 287 | - Deprecate =consult-apropos= 288 | 289 | * Version 0.20 (2022-10-16) 290 | 291 | - Bugfixes 292 | - Allow =consult-*-args= to be a string, or a list of strings or expressions. 293 | - Introduce face =consult-highlight-match= to highlight grep matches in the 294 | completion buffer. 295 | - Highlight full matches in =consult-line=, =consult-outline=, =consult-*grep= and 296 | =consult-flymake=. 297 | - Remove face =consult-preview-error=. 298 | - Deprecate =consult-line-point-placement= in favor of more general 299 | =consult-point-placement=, which is also used by the =consult-*grep= commands. 300 | - =consult-imenu=: Support imenu-after-jump-hook and non-default 301 | =imenu-default-goto-function= 302 | - =consult-history=: Add support for history index variables, which are updated 303 | after selection. 304 | - Deprecate support for Selectrum in favor of Vertico. If you use Selectrum 305 | consider switching to Vertico, Icomplete, Mct or default completion. 306 | 307 | * Version 0.19 (2022-09-09) 308 | 309 | - Bugfixes 310 | - Allow =consult-flymake= to work across all buffers in a project 311 | - Remove deprecated =consult-completing-read-multiple= 312 | - =consult-grep/git-grep/ripgrep=: Add =--fixed-strings= support 313 | - =consult-grep=: Respect =grep-find-ignored-directories/files= 314 | - =consult-org-heading=: Add tags to completion candidates 315 | - Add =consult-preview-excluded-files= 316 | - =consult-themes=: Support regexps 317 | 318 | * Version 0.18 (2022-05-25) 319 | 320 | - Bugfixes 321 | - Removed obsolete =consult-recent-file-filter= and =consult-preview-excluded-hooks= 322 | - Deprecate =consult-completing-read-multiple=. See #567 for details. 323 | - Add =consult--source-modified-buffer= 324 | 325 | * Version 0.17 (2022-04-22) 326 | 327 | - Bugfixes 328 | - Drop Emacs 26 support. 329 | - =consult-goto-line=: Use =goto-line-history= on Emacs 28. 330 | - =consult-customize=: Evaluate settings at runtime. This change makes it possible 331 | to use =thing-at-point= to overwrite the =:initial= and =:add-history= settings. 332 | - Rename =consult--read-config= to =consult--customize-alist= and change the format. 333 | The configuration is an alist. The car must be a command symbol. The cdr must 334 | be a plist of keys and expressions, where the expressions evaluate to the 335 | actual configuration values. 336 | - Mode hooks in previewed file buffers are delayed. The buffer is only fully 337 | initialized when leaving the minibuffer for recursive editing. 338 | - Increase =consult-preview-raw-size=. 339 | - Replace =consult-preview-excluded-hooks= by =consult-preview-allowed-hooks=. 340 | - Add =consult-preview-variables= to bind variables for file preview. 341 | - BREAKING API CHANGE of =consult--read=, =consult--prompt=, =consult--multi=: The 342 | state function protocol changed. The function gets notified of more completion 343 | state changes. See the docstring of =consult--with-preview= for details. 344 | - BREAKING API CHANGE of =consult--read=: The lookup function protocol changed. 345 | The function must now accept four or more arguments. 346 | - Remove unused =consult-preview-map=. 347 | - Remove unnecessary =consult-recent-file-filter=. Use =recentf-exclude= instead. 348 | - =consult--multi= sources can have a =:new= function to create candidates. 349 | When narrowed to a source, new candidates will be created by calling the 350 | respective =:new= function. 351 | - =consult--multi= returns =:match= information. =:match= can be nil, t, or new, 352 | depending on if the candidate does not exist, exists or has been created. 353 | - =consult-locate= treats the input literally to take advantage of the db index. 354 | 355 | * Version 0.16 (2022-03-08) 356 | 357 | - Bugfixes 358 | - Deprecate =consult-project-root-function= in favor of =consult-project-function=. 359 | - Preconfigure =consult-project-function= with a default function based 360 | on project.el. 361 | - Add =consult-project-buffer=, a variant of =consult-buffer= restricted to the 362 | current project. 363 | - Add =consult-register-prefix= option. 364 | - Introduced a generic and extensible =consult-register= implementation. 365 | - Lazy marker creation in =consult-line/outline= (performance improvements) 366 | 367 | * Version 0.15 (2022-01-31) 368 | 369 | - Bugfixes 370 | - =consult-xref=: Prettify the group titles, use =xref--group-name-for-display= 371 | if available. 372 | - =consult-focus-lines=: Thanks to @jdtsmith, the command is much faster and 373 | actually useable in large files. 374 | - Added Mct integration, auto refreshing of asynchronous Consult commands. 375 | 376 | * Version 0.14 (2021-12-31) 377 | 378 | - Bugfixes 379 | - Add =consult-recent-file-filter= 380 | - Rename =consult--source-(project-)file= to =consult-source-(project-)recent-file= 381 | - =consult-keep-lines= makes read-only buffers temporarily writable if confirmed 382 | 383 | * Version 0.13 (2021-11-12) 384 | 385 | - Bugfixes 386 | - =consult-register=: Add support for file register values. 387 | - Rename =consult-isearch= to =consult-isearch-history=. The command is a history 388 | browsing command and not a replacement for Isearch. 389 | - =consult-grep= support -[ABC] grep options 390 | - Add =consult-grep-context= face 391 | 392 | * Version 0.12 (2021-10-11) 393 | 394 | - Bugfixes 395 | - Removed obsolete =consult-project-imenu= and =consult-x-command= variables 396 | - =consult-grep=: Use ~--null~ argument to support file names with colons 397 | 398 | * Version 0.11 (2021-08-18) 399 | 400 | - Bugfixes only 401 | 402 | * Version 0.10 (2021-08-11) 403 | 404 | - =consult-mark=, =consult-global-mark=: Add optional marker list argument 405 | - =consult-completing-read-multiple=: New function 406 | - Rename =consult-project-imenu= to =consult-imenu-multi= 407 | - Add =consult-line-multi= to search multiple buffers 408 | - Removed obsolete =consult-yank=, =consult-async-default-split=, =consult-config= 409 | - =consult-ripgrep=: Use =--smart-case= 410 | - =consult-grep/git-grep=: Use =--ignore-case= 411 | - Deprecate =consult--command= in favor of =consult--config.= 412 | - =consult-find=: Use regular expressions instead of globbing/wildcards by default. 413 | Due to the changes to =consult-find= it is not possible anymore to configure 414 | =fd= as backend for =consult-find=. A replacement is documented in the wiki. 415 | - =consult-find/locate/man=: Add highlighting to the matching file/man page names. 416 | - =consult-grep/git-grep/ripgrep/find/locate=: Add support for multiple unordered 417 | patterns. Each of the input patterns must be matched. For example, 418 | =consult-find= transforms the input "first second third" to "first -and second 419 | -and third". 420 | - =consult-grep/git-grep/ripgrep=: Compute the highlighting based on the input, 421 | instead of relying on the ANSI-escaped output. This works better with multiple 422 | patterns, but may occasionally produce false highlighting. 423 | - Deprecate =consult-x-command= configuration variables in favor of =consult-x-args=. 424 | The variables have been renamed since the configuration format changed. 425 | - =consult-async-split-styles-alist=: Remove the =space= splitting style, since 426 | it has been obsoleted by the support for multiple unordered patterns. 427 | 428 | * Version 0.9 (2021-06-22) 429 | 430 | - Add =consult-preview-excluded-hooks= 431 | - =consult--read/consult--prompt=: Add =:inherit-input-method= argument 432 | - Add debouncing support for preview 433 | 434 | * Version 0.8 (2021-05-30) 435 | 436 | - Async commands: Do not fix vertical height in Selectrum. 437 | - =consult-imenu=: Deduplicate items (some imenu backends generate duplicates). 438 | - =consult-org-heading=: Deduplicate items. 439 | - =consult-buffer-filter=: Hide more buffers. 440 | - =consult-line=: Matching line preview overlay only in the selected window. 441 | - =consult-yank/completion-in-region=: Insertion preview only in selected window. 442 | - =consult-yank=: Rename to =consult-yank-from-kill-ring= (Emacs 28 naming). 443 | - =consult-yank= commands: =delete-selection-mode= support, added properties. 444 | - =consult-preview-at-point=, =consult-preview-at-point-mode=: New command and 445 | minor mode to preview candidate at point in =*Completions*= buffer. 446 | - Add =consult-async-split-style= and =consult-async-split-styles-alist=. 447 | - =consult-async-default-split=: Obsoleted in favor of =consult-async-split-style=. 448 | - Deprecate =consult-config= in favor of new =consult-customize= macro. 449 | - =consult-buffer=: Enable previews for files and bookmarks by default. 450 | - =consult-buffer=/=consult--multi=: Add support for =:preview-key= per source. 451 | - =consult-buffer=: Push visible buffers down in the buffer list. 452 | - =consult-flycheck=: Moved to separate repository prior to ELPA submission. 453 | - Submitted Consult to ELPA. 454 | 455 | * Version 0.7 (2021-04-29) 456 | 457 | - Bugfixes 458 | - =consult-buffer=: Respect =confirm-nonexistent-file-or-buffer= 459 | - =consult-widen-key=: Change default setting to twice the =consult-narrow-key= 460 | - =consult-flycheck=: Sort errors first 461 | - Added support for the Vertico completion system 462 | - Consult adds disambiguation suffixes as suffix instead of as prefix now 463 | for the commands =consult-line=, =consult-buffer=, etc. 464 | This enables support for the =basic= completion style and TAB completion. 465 | - =consult--read=: The =:title= function must accept two arguments now, 466 | the candidate string and a flag. If the flag is nil, the function should 467 | return the title of the candidate, otherwise the function should return the 468 | transformed candidate. 469 | - =consult-grep= and related commands: Strip the file name if grouping is used. 470 | - =consult-find/grep=: Ensure that the commands work with Tramp 471 | - =consult-outline=: Add narrowing 472 | - Added =consult-org-heading= and =consult-org-agenda= 473 | - =consult-line=: Highlight visual line during jump preview 474 | - =consult-line=: Start search at current line, add configuration variable 475 | =consult-start-from-top=. The starting point can be toggled by the prefix 476 | argument =C-u=. 477 | 478 | * Version 0.6 (2021-03-02) 479 | 480 | - Bugfixes 481 | - =consult-keep/focus-lines=: Align behavior on regions with built-in =keep-lines=. 482 | - =consult-buffer=: Enable file sources only when =recentf-mode= is enabled 483 | - =consult--multi=: Add =:default= flag, use flag for =consult--source-buffer= 484 | - Add =consult-grep-max-columns= to prevent performance issues for long lines 485 | - Add =consult-fontify-preserve= customization variable 486 | - =consult-line=: Quits Isearch, when started from an Isearch session 487 | - =consult-register-load=: Align prefix argument handling with =insert-register= 488 | - Rename =consult-error= to =consult-compile-error= 489 | - =consult-compile-error=: Allow calling the command from any buffer, 490 | use the errors from all compilation buffers related to the current buffer. 491 | - =consult-man=: Handle aggregated entries returned by mandoc 492 | - =consult-completion-in-region=: Added preview and =consult-preview-region= face 493 | - Added =consult-completion-in-region-styles= customization variable 494 | - Added =consult-xref=. The function can be set as =xref-show-xrefs-function= 495 | and =xref-show-definitions-function=. 496 | - Added support for the candidate grouping function =x-group-function= 497 | 498 | * Version 0.5 (2021-02-09) 499 | 500 | - Bugfixes 501 | - =consult-keep/focus-lines=: If region is active, operate only on the region. 502 | - =consult-register-format=: Do not truncate register strings. 503 | - =consult-buffer= multi sources: Ensure that original buffer is 504 | shown, when the currently selected source does not perform preview. 505 | - Add =consult-preview-raw-size= 506 | - Expose preview functionality for multi-source bookmarks/files 507 | - Multi sources: Add =:enabled=, =:state= and =:action= fields 508 | - =consult-imenu=: Add faces depending on item types 509 | 510 | * Version 0.4 (2021-02-01) 511 | 512 | - Bugfixes 513 | - Introduce multi sources, reimplement =consult-buffer= with multi sources 514 | - =consult-isearch=: Add preview highlighting 515 | - =consult-line=: Use =isearch-string= when invoked from running isearch 516 | 517 | * Version 0.3 (2021-01-28) 518 | 519 | - Bugfixes 520 | - New command =consult-isearch= 521 | - New functions =consult-register-format=, =consult-register-window=, 522 | removed =consult-register-preview= 523 | 524 | * Version 0.2 (2021-01-16) 525 | 526 | - Initial stable release 527 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+title: consult.el - Consulting completing-read 2 | #+author: Daniel Mendler 3 | #+language: en 4 | #+export_file_name: consult.texi 5 | #+texinfo_dir_category: Emacs misc features 6 | #+texinfo_dir_title: Consult: (consult). 7 | #+texinfo_dir_desc: Useful commands built on completing-read. 8 | 9 | #+html: GNU Emacs 10 | #+html: GNU ELPA 11 | #+html: GNU-devel ELPA 12 | #+html: MELPA 13 | #+html: MELPA Stable 14 | 15 | Consult provides search and navigation commands based on the Emacs completion 16 | function [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-Completion.html][completing-read]]. Completion allows you to quickly select an item from a 17 | list of candidates. Consult offers asynchronous and interactive =consult-grep= and 18 | =consult-ripgrep= commands, and the line-based search command =consult-line=. 19 | Furthermore Consult provides an advanced buffer switching command =consult-buffer= 20 | to switch between buffers, recently opened files, bookmarks and buffer-like 21 | candidates from other sources. Some of the Consult commands are enhanced 22 | versions of built-in Emacs commands. For example the command =consult-imenu= 23 | presents a flat list of the Imenu with [[#live-previews][live preview]], [[#narrowing-and-grouping][grouping and narrowing]]. 24 | Please take a look at the [[#available-commands][full list of commands]]. 25 | 26 | Consult is fully compatible with completion systems centered around the standard 27 | Emacs =completing-read= API, notably the default completion system, [[https://github.com/minad/vertico][Vertico]], [[https://github.com/protesilaos/mct][Mct]], 28 | and [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Icomplete.html][Icomplete]]. 29 | 30 | This package keeps the completion system specifics to a minimum. The ability of 31 | the Consult commands to work well with arbitrary completion systems is one of 32 | the main advantages of the package. Consult fits well into existing setups and 33 | it helps you to create a full completion environment out of small and 34 | independent components. 35 | 36 | You can combine the complementary packages [[https://github.com/minad/marginalia/][Marginalia]], [[https://github.com/oantolin/embark/][Embark]] and [[https://github.com/oantolin/orderless][Orderless]] with 37 | Consult. Marginalia enriches the completion display with annotations, e.g., 38 | documentation strings or file information. The versatile Embark package provides 39 | local actions, comparable to a context menu. These actions operate on the 40 | selected candidate in the minibuffer or at point in normal buffers. For example, 41 | when selecting from a list of files, Embark offers an action to delete the file. 42 | Additionally Embark offers a facility to collect completion candidates in a 43 | collect buffer. The section [[#embark-integration][Embark integration]] documents in detail how Consult 44 | and Embark work together. 45 | 46 | #+toc: headlines 8 47 | 48 | * Screenshots :noexport: 49 | 50 | #+caption: consult-grep 51 | [[https://github.com/minad/consult/blob/screenshots/consult-grep.gif?raw=true]] 52 | Fig. 1: Command =consult-git-grep= 53 | 54 | #+caption: consult-imenu 55 | [[https://github.com/minad/consult/blob/screenshots/consult-imenu.png?raw=true]] 56 | Fig. 2: Command =consult-imenu= 57 | 58 | #+caption: consult-line 59 | [[https://github.com/minad/consult/blob/screenshots/consult-line.png?raw=true]] 60 | Fig. 3: Command =consult-line= 61 | 62 | * Available commands 63 | :properties: 64 | :custom_id: available-commands 65 | :description: Navigation, search, editing commands and more 66 | :end: 67 | #+cindex: commands 68 | 69 | Most Consult commands follow the meaningful naming scheme =consult-=. 70 | Many commands implement a little known but convenient Emacs feature called 71 | "future history", which guesses what input the user wants. At a command prompt 72 | type =M-n= and typically Consult will insert the symbol or thing at point into 73 | the input. 74 | 75 | *TIP:* If you have [[https://github.com/minad/marginalia][Marginalia]] annotators activated, type =M-x ^consult= to see 76 | all Consult commands with their abbreviated description. Alternatively, type 77 | =C-h a ^consult= to get an overview of all Consult variables and functions with 78 | their descriptions. 79 | 80 | ** Virtual Buffers 81 | :properties: 82 | :description: Buffers, bookmarks and recent files 83 | :end: 84 | #+cindex: virtual buffers 85 | 86 | #+findex: consult-buffer 87 | #+findex: consult-buffer-other-window 88 | #+findex: consult-buffer-other-frame 89 | #+findex: consult-buffer-other-tab 90 | #+findex: consult-project-buffer 91 | #+findex: consult-recent-file 92 | #+findex: consult-bookmark 93 | - =consult-buffer=: Enhanced version of =switch-to-buffer= with support for virtual 94 | buffers. Supports live preview of buffers and narrowing to the virtual buffer 95 | types. You can type =f SPC= in order to narrow to recent files. Press =SPC= to 96 | show ephemeral buffers. Supported narrowing keys: 97 | - b Buffers 98 | - SPC Hidden buffers 99 | - * Modified buffers 100 | - f Files (Requires =recentf-mode=) 101 | - r File and buffer registers 102 | - m Bookmarks 103 | - p Project 104 | - B Project buffers 105 | - F Project files 106 | - R Project roots 107 | - Custom [[#multiple-sources][other sources]] configured in =consult-buffer-sources=. 108 | - =consult-buffer-other-window=, =consult-buffer-other-frame=, 109 | =consult-buffer-other-tab=: Variants of =consult-buffer=. 110 | - =consult-project-buffer=: Variant of =consult-buffer= restricted to buffers and 111 | recent files of the current project. You can add custom sources to 112 | =consult-project-buffer-sources=. The command may prompt you for a project if 113 | you invoke it from outside a project. 114 | - =consult-bookmark=: Select or create bookmark. To select bookmarks you might use the 115 | =consult-buffer= as an alternative, which can include a bookmark virtual buffer 116 | source. Note that =consult-bookmark= supports preview of bookmarks and 117 | narrowing. 118 | - =consult-recent-file=: Select from recent files with preview. 119 | You might prefer the powerful =consult-buffer= instead, which can include 120 | recent files as a virtual buffer source. The =recentf-mode= enables tracking of 121 | recent files. 122 | 123 | ** Editing 124 | :properties: 125 | :description: Commands useful for editing 126 | :end: 127 | #+cindex: editing 128 | 129 | #+findex: consult-yank-pop 130 | #+findex: consult-yank-from-kill-ring 131 | #+findex: consult-yank-replace 132 | #+findex: consult-kmacro 133 | - =consult-yank-from-kill-ring=: Enhanced version of =yank= to select an item 134 | from the =kill-ring=. The selected text previewed as overlay in the buffer. 135 | - =consult-yank-pop=: Enhanced version of =yank-pop= with DWIM-behavior, which 136 | either replaces the last =yank= by cycling through the =kill-ring=, or if there 137 | has not been a last =yank= consults the =kill-ring=. The selected text previewed 138 | as overlay in the buffer. 139 | - =consult-yank-replace=: Like =consult-yank-pop=, but always replaces the last 140 | =yank= with an item from the =kill-ring=. 141 | - =consult-kmacro=: Select macro from the macro ring and execute it. 142 | 143 | ** Register 144 | :properties: 145 | :description: Searching through registers and fast access 146 | :end: 147 | #+cindex: register 148 | 149 | #+findex: consult-register 150 | #+findex: consult-register-load 151 | #+findex: consult-register-store 152 | #+findex: consult-register-format 153 | #+findex: consult-register-window 154 | - =consult-register=: Select from list of registers. The command 155 | supports narrowing to register types and preview of marker positions. This 156 | command is useful to search the register contents. For quick access use the 157 | commands =consult-register-load=, =consult-register-store= or the built-in Emacs 158 | register commands. 159 | - =consult-register-format=: Set =register-preview-function= to this function for 160 | an enhanced register formatting. Used automatically by =consult-register-window=. 161 | - =consult-register-window=: Replace =register-preview= with this function for a 162 | better register window. See the [[#use-package-example][example configuration]]. 163 | - =consult-register-load=: Utility command to quickly load a register. 164 | The command either jumps to the register value or inserts it. 165 | - =consult-register-store=: Improved UI to store registers depending on the current 166 | context with an action menu. With an active region, store/append/prepend the 167 | contents, optionally deleting the region when a prefix argument is given. 168 | With a numeric prefix argument, store/add the number. Otherwise store point, 169 | file, buffer, frameset, window or kmacro. Usage examples: 170 | * =M-' x=: If no region is active, store point in register =x=. 171 | If a region is active, store the region in register =x=. 172 | * =M-' M-w x=: Store window configuration in register =x=. 173 | * =C-u 100 M-' x=: Store number in register =x=. 174 | 175 | ** Navigation 176 | :properties: 177 | :description: Mark rings, outlines and imenu 178 | :end: 179 | #+cindex: navigation 180 | 181 | #+findex: consult-goto-line 182 | #+findex: consult-mark 183 | #+findex: consult-global-mark 184 | #+findex: consult-outline 185 | #+findex: consult-imenu 186 | #+findex: consult-imenu-multi 187 | - =consult-goto-line=: Jump to line number enhanced with live preview. This is a 188 | drop-in replacement for =goto-line=. Enter a line number to jump to the first 189 | column of the given line. Alternatively enter =line:column= in order to jump to 190 | a specific column. 191 | - =consult-mark=: Jump to a marker in the =mark-ring=. Supports live 192 | preview and recursive editing. 193 | - =consult-global-mark=: Jump to a marker in the =global-mark-ring=. 194 | Supports live preview and recursive editing. 195 | - =consult-outline=: Jump to a heading of the outline. Supports narrowing 196 | to a heading level, live preview and recursive editing. 197 | - =consult-imenu=: Jump to imenu item in the current buffer. Supports 198 | live preview, recursive editing and narrowing. 199 | - =consult-imenu-multi=: Jump to imenu item in project buffers, with 200 | the same major mode as the current buffer. Supports live preview, 201 | recursive editing and narrowing. This feature has been inspired by 202 | [[https://github.com/vspinu/imenu-anywhere][imenu-anywhere]]. 203 | 204 | ** Search 205 | :properties: 206 | :description: Line search, grep and file search 207 | :end: 208 | #+cindex: search 209 | 210 | #+findex: consult-line 211 | #+findex: consult-line-multi 212 | #+findex: consult-keep-lines 213 | #+findex: consult-focus-lines 214 | - =consult-line=: Enter search string and select from matching lines. 215 | Supports live preview and recursive editing. The symbol at point and the 216 | recent Isearch string are added to the "future history" and can be accessed 217 | by pressing =M-n=. When =consult-line= is bound to the =isearch-mode-map= and 218 | is invoked during a running Isearch, it will use the current Isearch string. 219 | - =consult-line-multi=: Search dynamically across multiple buffers. By default 220 | search across project buffers. If invoked with a prefix argument search across 221 | all buffers. The candidates are computed on demand based on the input. The 222 | command behaves like =consult-grep=, but operates on buffers instead of files. 223 | - =consult-keep-lines=: Replacement for =keep/flush-lines= which uses the current 224 | completion style for filtering the buffer. The function updates the buffer 225 | while typing. In particular =consult-keep-lines= can narrow down an exported 226 | Embark collect buffer further, relying on the same completion filtering as 227 | ~completing-read~. If the input begins with the negation operator, i.e., ~! SPC~, 228 | the filter matches the complement. If a region is active, the region restricts 229 | the filtering. 230 | - =consult-focus-lines=: Temporarily hide lines by filtering them using the 231 | current completion style. Call with =C-u= prefix argument in order to show the 232 | hidden lines again. If the input begins with the negation operator, i.e., ~! 233 | SPC~, the filter matches the complement. In contrast to =consult-keep-lines= this 234 | function does not edit the buffer. If a region is active, the region restricts 235 | the filtering. 236 | 237 | ** Grep and Find 238 | :properties: 239 | :description: Searching through the filesystem 240 | :end: 241 | #+cindex: grep 242 | #+cindex: find 243 | #+cindex: locate 244 | 245 | #+findex: consult-grep 246 | #+findex: consult-ripgrep 247 | #+findex: consult-git-grep 248 | #+findex: consult-find 249 | #+findex: consult-fd 250 | #+findex: consult-locate 251 | - =consult-grep=, =consult-ripgrep=, =consult-git-grep=: Search for regular expression 252 | in files. Consult invokes Grep asynchronously, while you enter the search 253 | term. After at least =consult-async-min-input= characters, the search gets 254 | started. Consult splits the input string into two parts, if the first 255 | character is a punctuation character, like =#=. For example 256 | =#regexps#filter-string=, is split at the second =#=. The string =regexps= is passed 257 | to Grep. Note that Consult transforms Emacs regular expressions to expressions 258 | understand by the search program. Always use Emacs regular expressions at the 259 | prompt. If you enter multiple regular expressions separated by space only 260 | lines matching all regular expressions are shown. In order to match space 261 | literally, escape the space with a backslash. The =filter-string= is passed to 262 | the /fast/ Emacs filtering to further narrow down the list of matches. This is 263 | particularly useful if you are using an advanced completion style like 264 | orderless. =consult-grep= supports preview. =consult-grep= searches the current 265 | [[#project-support][project directory]] if a project is found. Otherwise the =default-directory= is 266 | searched. If =consult-grep= is invoked with prefix argument =C-u M-s g=, you can 267 | specify one or more comma-separated files and directories manually. If invoked 268 | with two prefix arguments =C-u C-u M-s g=, you can first select a project if you 269 | are not yet inside a project. 270 | - =consult-find=, =consult-fd=, =consult-locate=: Find file by matching the path 271 | against a regexp. Like for =consult-grep=, either the project root or the 272 | current directory is the root directory for the search. The input string is 273 | treated similarly to =consult-grep=, where the first part is passed to find, and 274 | the second part is used for Emacs filtering. Prefix arguments to =consult-find= 275 | work just like those for the consult grep commands. 276 | 277 | ** Compilation 278 | :properties: 279 | :description: Jumping to references and compilation errors 280 | :end: 281 | #+cindex: compilation errors 282 | 283 | #+findex: consult-compile-error 284 | #+findex: consult-flymake 285 | #+findex: consult-xref 286 | - =consult-compile-error=: Jump to a compilation error or grep search result. 287 | Supports live preview narrowing and recursive editing. 288 | - =consult-flymake=: Jump to Flymake diagnostic. Supports live preview and 289 | recursive editing. The command supports narrowing. Press =e SPC=, =w SPC=, =n SPC= 290 | to only show errors, warnings and notes respectively. 291 | - =consult-xref=: Integration with xref. This function can be set as 292 | =xref-show-xrefs-function= and =xref-show-definitions-function=. 293 | 294 | ** Histories 295 | :properties: 296 | :description: Navigating histories 297 | :end: 298 | #+cindex: history 299 | 300 | #+findex: consult-complex-command 301 | #+findex: consult-history 302 | #+findex: consult-isearch-history 303 | - =consult-complex-command=: Select a command from the 304 | =command-history=. This command is a =completing-read= version of 305 | =repeat-complex-command= and is also a replacement for the =command-history= 306 | command from chistory.el. 307 | - =consult-history=: Insert a string from the current buffer history, for example 308 | the Eshell or Comint history. You can also invoke this command from the 309 | minibuffer. In that case =consult-history= uses the history stored in the 310 | =minibuffer-history-variable=. If you prefer =completion-at-point=, take a look at 311 | =cape-history= from the [[https://github.com/minad/cape][Cape]] package. 312 | - =consult-isearch-history=: During an Isearch session, this command picks a 313 | search string from history and continues the search with the newly selected 314 | string. Outside of Isearch, the command allows you to pick a string from the 315 | history and starts a new Isearch. =consult-isearch-history= acts as a drop-in 316 | replacement for =isearch-edit-string=. 317 | 318 | ** Modes 319 | :properties: 320 | :description: Toggling minor modes and executing commands 321 | :end: 322 | #+cindex: minor mode 323 | #+cindex: major mode 324 | 325 | #+findex: consult-minor-mode-menu 326 | #+findex: consult-mode-command 327 | - =consult-minor-mode-menu=: Enable/disable minor mode. Supports 328 | narrowing to on/off/local/global modes by pressing =i/o/l/g SPC= 329 | respectively. 330 | - =consult-mode-command=: Run a command from the currently active minor or major 331 | modes. Supports narrowing to local-minor/global-minor/major mode via the keys 332 | =l/g/m=. 333 | 334 | ** Org Mode 335 | :properties: 336 | :description: Org-specific commands 337 | :end: 338 | 339 | #+findex: consult-org-heading 340 | #+findex: consult-org-agenda 341 | - =consult-org-heading=: Variant of =consult-imenu= or =consult-outline= for Org 342 | buffers. The headline and its ancestors headlines are separated by slashes. 343 | Supports narrowing by heading level, priority and TODO keyword, as well as live 344 | preview and recursive editing. 345 | - =consult-org-agenda=: Jump to an Org agenda heading. Supports narrowing by 346 | heading level, priority and TODO keyword, as well as live preview and 347 | recursive editing. 348 | ** Help 349 | :properties: 350 | :description: Searching through help 351 | :end: 352 | 353 | #+findex: consult-info 354 | #+findex: consult-info-define 355 | #+findex: consult-man 356 | - =consult-man=: Find Unix man page, via Unix =apropos= or =man -k=. =consult-man= opens 357 | the selected man page using the Emacs =man= command. Supports live preview of 358 | the theme while scrolling through the candidates. 359 | - =consult-info=: Full text search through info pages. If the command is invoked 360 | from within an ~*info*~ buffer, it will search through the current manual. You 361 | may want to create your own =consult-info-*= commands which search through a 362 | predefined set of info pages. You can use the function =consult-info-define= to 363 | define commands =consult-info-emacs=, =consult-info-completion=, =consult-info-org=, 364 | and so on: 365 | #+begin_src emacs-lisp 366 | (consult-info-define "emacs" "efaq" "elisp" "cl" "compat" "eshell") 367 | (consult-info-define 'completion 368 | "vertico" "consult" "marginalia" "orderless" 369 | "embark" "corfu" "cape" "tempel") 370 | (consult-info-define "org") 371 | (consult-info-define "gnus") 372 | (consult-info-define "magit") 373 | #+end_src 374 | 375 | ** Miscellaneous 376 | :properties: 377 | :description: Various other useful commands 378 | :end: 379 | 380 | #+findex: consult-completion-in-region 381 | #+findex: consult-theme 382 | #+findex: consult-preview-at-point 383 | #+findex: consult-preview-at-point-mode 384 | - =consult-theme=: Select a theme and disable all currently enabled themes. 385 | Supports live preview of the theme while scrolling through the candidates. 386 | - =consult-preview-at-point= and =consult-preview-at-point-mode=: Command and minor 387 | mode which previews the candidate at point in the =*Completions*= buffer. This 388 | mode is relevant if you use [[https://git.sr.ht/~protesilaos/mct][Mct]] or the default =*Completions*= UI. 389 | - =consult-completion-in-region=: In case you don't use [[https://github.com/minad/corfu][Corfu]] as your in-buffer 390 | completion UI, this function can be set as =completion-in-region-function=. Then 391 | your minibuffer completion UI (e.g., Vertico or Icomplete) will be used for 392 | =completion-at-point=. 393 | #+begin_src emacs-lisp 394 | (setq completion-in-region-function #'consult-completion-in-region) 395 | #+end_src 396 | Instead of =consult-completion-in-region=, you may prefer to see the completions 397 | directly in the buffer as a small popup. In that case, I recommend the [[https://github.com/minad/corfu][Corfu]] 398 | package. There is a technical limitation of =consult-completion-in-region= in 399 | combination with the Lsp modes. The Lsp server relies on the input at point, 400 | in order to generate refined candidate strings. Since the completion is 401 | transferred from the original buffer to the minibuffer, the server does not 402 | receive the updated input. In contrast, in-buffer Lsp completion for example 403 | via Corfu works properly since the completion takes place directly in the 404 | original buffer. 405 | 406 | * Special features 407 | :properties: 408 | :description: Enhancements over built-in `completing-read' 409 | :end: 410 | 411 | Consult enhances =completing-read= with live previews of candidates, additional 412 | narrowing capabilities to candidate groups and asynchronously generated 413 | candidate lists. The internal =consult--read= function, which is used by most 414 | Consult commands, is a thin wrapper around =completing-read= and provides the 415 | special functionality. In order to support multiple candidate sources there 416 | exists the high-level function =consult--multi=. The architecture of Consult 417 | allows it to work with different completion systems in the backend, while still 418 | offering advanced features. 419 | 420 | ** Live previews 421 | :properties: 422 | :description: Preview the currently selected candidate 423 | :custom_id: live-previews 424 | :end: 425 | #+cindex: preview 426 | 427 | Some Consult commands support live previews. For example when you scroll through 428 | the items of =consult-line=, the buffer will scroll to the corresponding position. 429 | It is possible to jump back and forth between the minibuffer and the buffer to 430 | perform recursive editing while the search is ongoing. 431 | 432 | Consult enables previews by default. You can disable them by adjusting the 433 | =consult-preview-key= variable. Furthermore it is possible to specify keybindings 434 | which trigger the preview manually as shown in the [[#use-package-example][example configuration]]. The 435 | default setting of =consult-preview-key= is =any= which means that Consult triggers 436 | the preview /immediately/ on any key press when the selected candidate changes. 437 | You can configure each command individually with its own =:preview-key=. The 438 | following settings are possible: 439 | 440 | - Automatic and immediate ='any= 441 | - Automatic and delayed =(list :debounce 0.5 'any)= 442 | - Manual and immediate ="M-."= 443 | - Manual and delayed =(list :debounce 0.5 "M-.")= 444 | - Disabled =nil= 445 | 446 | A safe recommendation is to leave automatic immediate previews enabled in 447 | general and disable the automatic preview only for commands where the preview 448 | may be expensive due to file loading. Internally, Consult uses the 449 | value of =this-command= to determine the =:preview-key= 450 | customized. This means that if you wrap a =consult-*= command within 451 | your own function or command, you will also need to add the name of 452 | /your custom command/ to the =consult-customize= call in order for it 453 | to be considered. 454 | 455 | #+begin_src emacs-lisp 456 | (consult-customize 457 | consult-ripgrep consult-git-grep consult-grep consult-man 458 | consult-bookmark consult-recent-file consult-xref 459 | consult--source-bookmark consult--source-file-register 460 | consult--source-recent-file consult--source-project-recent-file 461 | ;; my/command-wrapping-consult ;; disable auto previews inside my command 462 | :preview-key '(:debounce 0.4 any) ;; Option 1: Delay preview 463 | ;; :preview-key "M-.") ;; Option 2: Manual preview 464 | #+end_src 465 | 466 | In this case one may wonder what the difference is between using an Embark 467 | action on the current candidate in comparison to a manually triggered preview. 468 | The main difference is that the files opened by manual preview are closed again 469 | after the completion session. During preview some functionality is disabled to 470 | improve the performance, see for example the customization variables 471 | =consult-preview-variables= and =consult-preview-allowed-hooks=. Only hooks listed 472 | in =consult-preview-allowed-hooks= are executed. This variable applies to 473 | =find-file-hook=, =change-major-mode-hook= and mode hooks, e.g., =prog-mode-hook=. In 474 | order to enable additional font locking during preview, add the corresponding 475 | hooks to the allow list. The following code demonstrates this for [[https://github.com/minad/org-modern][org-modern]] and 476 | [[https://github.com/tarsius/hl-todo][hl-todo]]. 477 | 478 | #+begin_src emacs-lisp 479 | ;; local modes added to prog-mode hooks 480 | (add-to-list 'consult-preview-allowed-hooks 'hl-todo-mode) 481 | (add-to-list 'consult-preview-allowed-hooks 'elide-head-mode) 482 | ;; enabled global modes 483 | (add-to-list 'consult-preview-allowed-hooks 'global-org-modern-mode) 484 | (add-to-list 'consult-preview-allowed-hooks 'global-hl-todo-mode) 485 | #+end_src 486 | 487 | Files larger than =consult-preview-partial-size= are previewed partially. Delaying 488 | the preview is also useful for =consult-theme=, since the theme preview is slow. 489 | The delay results in a smoother UI experience. 490 | 491 | #+begin_src emacs-lisp 492 | ;; Preview on any key press, but delay 0.5s 493 | (consult-customize consult-theme :preview-key '(:debounce 0.5 any)) 494 | ;; Preview immediately on M-., on up/down after 0.5s, on any other key after 1s 495 | (consult-customize consult-theme 496 | :preview-key 497 | '("M-." 498 | :debounce 0.5 "" "" 499 | :debounce 1 any)) 500 | #+end_src 501 | 502 | ** Narrowing and grouping 503 | :properties: 504 | :description: Restricting the completion to a candidate group 505 | :custom_id: narrowing-and-grouping 506 | :end: 507 | #+cindex: narrowing 508 | 509 | Consult has special support for candidate groups. If the completion UI supports 510 | the grouping functionality, the UI separates the groups with thin lines and 511 | shows group titles. Grouping is useful if the list of candidates consists of 512 | candidates of multiple types or candidates from [[#multiple-sources][multiple sources]], like the 513 | =consult-buffer= command, which shows both buffers and recently opened files. Note 514 | that you can disable the group titles by setting the =:group= property of the 515 | corresponding command to nil using the =consult-customize= macro. 516 | 517 | By entering a narrowing prefix or by pressing a narrowing key it is possible to 518 | restrict the completion candidates to a certain candidate group. When you use 519 | the =consult-buffer= command, you can enter the prefix =b SPC= to restrict list of 520 | candidates to buffers only. If you press =DEL= afterwards, the full candidate list 521 | will be shown again. Furthermore a narrowing prefix key and a widening key can 522 | be configured which can be pressed to achieve the same effect, see the 523 | configuration variables =consult-narrow-key= and =consult-widen-key=. 524 | 525 | After pressing =consult-narrow-key=, the possible narrowing keys can be shown by 526 | pressing =C-h=. When pressing =C-h= after some prefix key, the =prefix-help-command= 527 | is invoked, which shows the keybinding help window by default. As a more compact 528 | alternative, there is the =consult-narrow-help= command which can be bound to a 529 | key, for example =?= or =C-h= in the =consult-narrow-map=, as shown in the [[#use-package-example][example 530 | configuration]]. If [[https://github.com/justbur/emacs-which-key][which-key]] is installed, the narrowing keys are automatically 531 | shown in the which-key window after pressing the =consult-narrow-key=. 532 | 533 | ** Asynchronous search 534 | :properties: 535 | :description: Filtering asynchronously generated candidate lists 536 | :end: 537 | #+cindex: asynchronous search 538 | 539 | Consult has support for asynchronous generation of candidate lists. This feature 540 | is used for search commands like =consult-grep=, where the list of matches is 541 | generated dynamically while the user is typing a regular expression. The grep 542 | process is executed in the background. When modifying the regular expression, 543 | the background process is terminated and a new process is started with the 544 | modified regular expression. 545 | 546 | The matches, which have been found, can then be narrowed using the installed 547 | Emacs completion-style. This can be powerful if you are using for example the 548 | =orderless= completion style. 549 | 550 | This two-level filtering is possible by splitting the input string. Part of the 551 | input string is treated as input to grep and part of the input is used for 552 | filtering. There are multiple splitting styles available, configured in 553 | ~consult-async-split-styles-alist~: =nil=, =comma=, =semicolon= and =perl=. The default 554 | splitting style is configured with the variable ~consult-async-split-style~. 555 | 556 | With the =comma= and =semicolon= splitting styles, the first word before the comma 557 | or semicolon is passed to grep, the remaining string is used for filtering. The 558 | =nil= splitting style does not perform any splitting, the whole input is passed to 559 | grep. 560 | 561 | The =perl= splitting style splits the input string at a punctuation character, 562 | using a similar syntax as Perl regular expressions. 563 | 564 | Examples: 565 | 566 | - =#defun=: Search for "defun" using grep. 567 | - =#consult embark=: Search for both "consult" and "embark" using grep in any order. 568 | - =#first.*second=: Search for "first" followed by "second" using grep. 569 | - =#\(consult\|embark\)=: Search for "consult" or "embark" using grep. Note the 570 | usage of Emacs-style regular expressions. 571 | - =#defun#consult=: Search for "defun" using grep, filter with the word 572 | "consult". 573 | - =/defun/consult=: It is also possible to use other punctuation 574 | characters. 575 | - =#to#=: Force searching for "to" using grep, since the grep pattern 576 | must be longer than =consult-async-min-input= characters by default. 577 | - =#defun -- --invert-match#=: Pass argument =--invert-match= to grep. 578 | 579 | Asynchronous processes like =find= and =grep= create an error log buffer 580 | =_*consult-async*= (note the leading space), which is useful for 581 | troubleshooting. The prompt has a small indicator showing the process status: 582 | 583 | - =:= the usual prompt colon, before input is provided. 584 | - =*= with warning face, the process is running. 585 | - =:= with success face, success, process exited with an error code of zero. 586 | - =!= with error face, failure, process exited with a nonzero error code. 587 | - =;= with error face, interrupted, for example if more input is provided. 588 | 589 | ** Multiple sources 590 | :properties: 591 | :description: Combining candidates from different sources 592 | :custom_id: multiple-sources 593 | :end: 594 | #+cindex: multiple sources 595 | 596 | Multiple static and asynchronous candidate sources can be combined. This feature 597 | is used by the =consult-buffer= command to present buffer-like candidates in a 598 | single menu for quick access. By default =consult-buffer= includes buffers, 599 | bookmarks, recent files and project-specific buffers and files. The 600 | =consult-buffer-sources= variable configures the list of sources. Arbitrary custom 601 | sources can be added to this list. 602 | 603 | As an example, the bookmark source is defined as follows: 604 | 605 | #+begin_src emacs-lisp 606 | (defvar consult--source-bookmark 607 | `(:name "Bookmark" 608 | :narrow ?m 609 | :category bookmark 610 | :face consult-bookmark 611 | :history bookmark-history 612 | :items ,#'bookmark-all-names 613 | :action ,#'consult--bookmark-action)) 614 | #+end_src 615 | 616 | Either the =:items= or the =:async= source field is required: 617 | - =:items= List of strings to select from or function returning list of strings. 618 | The strings can carry metadata in text properties, which is then available to 619 | the =:annotate=, =:action= and =:state= functions. The list can also consist of 620 | pairs, with the string in the =car= used for display and the =cdr= the actual 621 | candidate. 622 | - =:async= Alternative to =:items= for asynchronous sources. See the docstring for 623 | details. 624 | 625 | Optional source fields: 626 | - =:name= Name of the source, used for narrowing, group titles and annotations. 627 | - =:narrow= Narrowing character, =(char . string)= pair or list of pairs. 628 | - =:category= Completion category. 629 | - =:preview-key= Preview key or keys which trigger preview. 630 | - =:enabled= Function which must return t if the source is enabled. 631 | - =:hidden= When t candidates of this source are hidden by default. 632 | - =:face= Face used for highlighting the candidates. 633 | - =:annotate= Annotation function called for each candidate, returns string. 634 | - =:history= Name of history variable to add selected candidate. 635 | - =:default= Must be t if the first item of the source is the default value. 636 | - =:action= Function called with the selected candidate. 637 | - =:new= Function called with new candidate name, only if =:require-match= is nil. 638 | - =:state= State constructor for the source, must return the state function. 639 | - Other source fields can be added specifically to the use case. 640 | 641 | The =:state= and =:action= fields of the sources deserve a longer explanation. The 642 | =:action= function takes a single argument and is only called after selection with 643 | the selected candidate, if the selection has not been aborted. This 644 | functionality is provided for convenience and easy definition of sources. The 645 | =:state= field is more general. The =:state= function is a constructor function 646 | without arguments, which can perform some setup necessary for the preview. It 647 | must return a closure which takes an ACTION and a CANDIDATE argument. See the 648 | docstring of =consult--with-preview= for more details about the ACTION argument. 649 | 650 | By default, =consult-buffer= previews buffers, bookmarks and files. Loading recent 651 | files or bookmarks can result in expensive operations. However it is possible to 652 | configure a manual preview as follows. 653 | 654 | #+begin_src emacs-lisp 655 | (consult-customize 656 | consult--source-bookmark consult--source-file-register 657 | consult--source-recent-file consult--source-project-recent-file 658 | :preview-key "M-.") 659 | #+end_src 660 | 661 | Sources can be added directly to the =consult-buffer-source= list for convenience. 662 | For example, the following source lists all Org buffers and lets you create new 663 | ones. 664 | 665 | #+begin_src emacs-lisp 666 | (defvar org-source 667 | (list :name "Org Buffer" 668 | :category 'buffer 669 | :narrow ?o 670 | :face 'consult-buffer 671 | :history 'buffer-name-history 672 | :state #'consult--buffer-state 673 | :new 674 | (lambda (name) 675 | (with-current-buffer (get-buffer-create name) 676 | (insert "#+title: " name "\n\n") 677 | (org-mode) 678 | (consult--buffer-action (current-buffer)))) 679 | :items 680 | (lambda () 681 | (consult--buffer-query :mode 'org-mode :as #'consult--buffer-pair)))) 682 | 683 | (add-to-list 'consult-buffer-sources 'org-source 'append) 684 | #+end_src 685 | 686 | One can create similar sources for other major modes. See the [[https://github.com/minad/consult/wiki][Consult wiki]] for 687 | many additional source examples. See also the documentation of =consult-buffer= 688 | and of the internal =consult--multi= API. The function =consult--multi= can be used 689 | to create new multi-source commands. 690 | 691 | ** Embark integration 692 | :properties: 693 | :description: Actions, Grep/Occur-buffer export 694 | :custom_id: embark-integration 695 | :end: 696 | #+cindex: embark 697 | 698 | *NOTE*: Install the =embark-consult= package from MELPA, which provides 699 | Consult-specific Embark actions and the Occur buffer export. 700 | 701 | Embark is a versatile package which offers context dependent actions, comparable 702 | to a context menu. See the [[https://github.com/oantolin/embark][Embark manual]] for an extensive description of its 703 | capabilities. 704 | 705 | Actions are commands which can operate on the currently selected candidate (or 706 | target in Embark terminology). When completing files, for example the 707 | =delete-file= command is offered. With Embark you can execute arbitrary commands 708 | on the currently selected candidate via =M-x=. 709 | 710 | Furthermore Embark provides the =embark-collect= command, which collects 711 | candidates and presents them in an Embark collect buffer, where further actions 712 | can be applied to them. A related feature is the =embark-export= command, which 713 | exports candidate lists to a buffer of a special type. For example in the case 714 | of file completion, a Dired buffer is opened. 715 | 716 | In the context of Consult, particularly exciting is the possibility to export 717 | the matching lines from =consult-line=, =consult-outline=, =consult-mark= and 718 | =consult-global-mark=. The matching lines are exported to an Occur buffer where 719 | they can be edited via the =occur-edit-mode= (press key =e=). Similarly, Embark 720 | supports exporting the matches found by =consult-grep=, =consult-ripgrep= and 721 | =consult-git-grep= to a Grep buffer, where the matches across files can be edited, 722 | via =grep-edit-mode= on Emacs 31 (or via the [[https://github.com/mhayashi1120/Emacs-wgrep][wgrep]] package). These three workflows 723 | are symmetric. 724 | 725 | + =consult-line= -> =embark-export= to =occur-mode= buffer -> =occur-edit-mode= for editing of matches. 726 | + =consult-grep= -> =embark-export= to =grep-mode= buffer -> =grep-edit-mode= for editing of matches. 727 | + =consult-find= -> =embark-export= to =dired-mode= buffer -> =wdired-change-to-wdired-mode= for editing. 728 | 729 | * Configuration 730 | :properties: 731 | :description: Example configuration and customization variables 732 | :end: 733 | 734 | Consult can be installed from [[https://elpa.gnu.org/packages/consult.html][ELPA]] or [[https://melpa.org/#/consult][MELPA]] via the Emacs built-in package 735 | manager. Alternatively it can be directly installed from the development 736 | repository via other non-standard package managers. 737 | 738 | There is the [[https://github.com/minad/consult/wiki][Consult wiki]], where additional configuration examples can be 739 | contributed. 740 | 741 | *IMPORTANT:* It is recommended that you enable [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical binding]] in your 742 | configuration. Many Consult-related code snippets require lexical binding, since 743 | they use lambdas and closures. 744 | 745 | ** Use-package example 746 | :properties: 747 | :description: Configuration example based on use-package 748 | :custom_id: use-package-example 749 | :end: 750 | #+cindex: use-package 751 | 752 | The Consult package only provides commands and does not add any keybindings or 753 | modes. Therefore the package is non-intrusive but requires a little setup 754 | effort. While the configuration example is long, it consists essentially of key 755 | bindings only, such that the risk of interference with other Emacs functionality 756 | is minimized. 757 | 758 | In order to use the Consult commands, it is recommended to add keybindings for 759 | commands which are accessed often. Rarely used commands can be invoked via =M-x=. 760 | Feel free to only bind the commands you consider useful to your workflow. The 761 | configuration shown here relies on the =use-package= macro, which is a convenient 762 | tool to manage package configurations. 763 | 764 | *NOTE:* There is the [[https://github.com/minad/consult/wiki][Consult wiki]], where you can contribute additional 765 | configuration examples. 766 | 767 | #+begin_src emacs-lisp 768 | ;; Example configuration for Consult 769 | (use-package consult 770 | ;; Replace bindings. Lazily loaded by `use-package'. 771 | :bind (;; C-c bindings in `mode-specific-map' 772 | ("C-c M-x" . consult-mode-command) 773 | ("C-c h" . consult-history) 774 | ("C-c k" . consult-kmacro) 775 | ("C-c m" . consult-man) 776 | ("C-c i" . consult-info) 777 | ([remap Info-search] . consult-info) 778 | ;; C-x bindings in `ctl-x-map' 779 | ("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command 780 | ("C-x b" . consult-buffer) ;; orig. switch-to-buffer 781 | ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window 782 | ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame 783 | ("C-x t b" . consult-buffer-other-tab) ;; orig. switch-to-buffer-other-tab 784 | ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump 785 | ("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer 786 | ;; Custom M-# bindings for fast register access 787 | ("M-#" . consult-register-load) 788 | ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated) 789 | ("C-M-#" . consult-register) 790 | ;; Other custom bindings 791 | ("M-y" . consult-yank-pop) ;; orig. yank-pop 792 | ;; M-g bindings in `goto-map' 793 | ("M-g e" . consult-compile-error) 794 | ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck 795 | ("M-g g" . consult-goto-line) ;; orig. goto-line 796 | ("M-g M-g" . consult-goto-line) ;; orig. goto-line 797 | ("M-g o" . consult-outline) ;; Alternative: consult-org-heading 798 | ("M-g m" . consult-mark) 799 | ("M-g k" . consult-global-mark) 800 | ("M-g i" . consult-imenu) 801 | ("M-g I" . consult-imenu-multi) 802 | ;; M-s bindings in `search-map' 803 | ("M-s d" . consult-find) ;; Alternative: consult-fd 804 | ("M-s c" . consult-locate) 805 | ("M-s g" . consult-grep) 806 | ("M-s G" . consult-git-grep) 807 | ("M-s r" . consult-ripgrep) 808 | ("M-s l" . consult-line) 809 | ("M-s L" . consult-line-multi) 810 | ("M-s k" . consult-keep-lines) 811 | ("M-s u" . consult-focus-lines) 812 | ;; Isearch integration 813 | ("M-s e" . consult-isearch-history) 814 | :map isearch-mode-map 815 | ("M-e" . consult-isearch-history) ;; orig. isearch-edit-string 816 | ("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string 817 | ("M-s l" . consult-line) ;; needed by consult-line to detect isearch 818 | ("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch 819 | ;; Minibuffer history 820 | :map minibuffer-local-map 821 | ("M-s" . consult-history) ;; orig. next-matching-history-element 822 | ("M-r" . consult-history)) ;; orig. previous-matching-history-element 823 | 824 | ;; Enable automatic preview at point in the *Completions* buffer. This is 825 | ;; relevant when you use the default completion UI. 826 | :hook (completion-list-mode . consult-preview-at-point-mode) 827 | 828 | ;; The :init configuration is always executed (Not lazy) 829 | :init 830 | 831 | ;; Tweak the register preview for `consult-register-load', 832 | ;; `consult-register-store' and the built-in commands. This improves the 833 | ;; register formatting, adds thin separator lines, register sorting and hides 834 | ;; the window mode line. 835 | (advice-add #'register-preview :override #'consult-register-window) 836 | (setq register-preview-delay 0.5) 837 | 838 | ;; Use Consult to select xref locations with preview 839 | (setq xref-show-xrefs-function #'consult-xref 840 | xref-show-definitions-function #'consult-xref) 841 | 842 | ;; Configure other variables and modes in the :config section, 843 | ;; after lazily loading the package. 844 | :config 845 | 846 | ;; Optionally configure preview. The default value 847 | ;; is 'any, such that any key triggers the preview. 848 | ;; (setq consult-preview-key 'any) 849 | ;; (setq consult-preview-key "M-.") 850 | ;; (setq consult-preview-key '("S-" "S-")) 851 | ;; For some commands and buffer sources it is useful to configure the 852 | ;; :preview-key on a per-command basis using the `consult-customize' macro. 853 | (consult-customize 854 | consult-theme :preview-key '(:debounce 0.2 any) 855 | consult-ripgrep consult-git-grep consult-grep consult-man 856 | consult-bookmark consult-recent-file consult-xref 857 | consult--source-bookmark consult--source-file-register 858 | consult--source-recent-file consult--source-project-recent-file 859 | ;; :preview-key "M-." 860 | :preview-key '(:debounce 0.4 any)) 861 | 862 | ;; Optionally configure the narrowing key. 863 | ;; Both < and C-+ work reasonably well. 864 | (setq consult-narrow-key "<") ;; "C-+" 865 | 866 | ;; Optionally make narrowing help available in the minibuffer. 867 | ;; You may want to use `embark-prefix-help-command' or which-key instead. 868 | ;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help) 869 | ) 870 | #+end_src 871 | 872 | ** Custom variables 873 | :properties: 874 | :description: Short description of all customization settings 875 | :end: 876 | #+cindex: customization 877 | 878 | *TIP:* If you have [[https://github.com/minad/marginalia][Marginalia]] installed, type =M-x customize-variable RET 879 | ^consult= to see all Consult-specific customizable variables with their current 880 | values and abbreviated description. Alternatively, type =C-h a ^consult= to get 881 | an overview of all Consult variables and functions with their descriptions. 882 | 883 | | Variable | Description | 884 | |----------------------------------+-----------------------------------------------------| 885 | | consult-after-jump-hook | Functions to call after jumping to a location | 886 | | consult-async-input-debounce | Input debounce for asynchronous commands | 887 | | consult-async-input-throttle | Input throttle for asynchronous commands | 888 | | consult-async-min-input | Minimum numbers of input characters | 889 | | consult-async-refresh-delay | Refresh delay for asynchronous commands | 890 | | consult-async-split-style | Splitting style used for async commands | 891 | | consult-async-split-styles-alist | Available splitting styles used for async commands | 892 | | consult-async-indicator | Async indicator characters | 893 | | consult-bookmark-narrow | Narrowing configuration for =consult-bookmark= | 894 | | consult-buffer-filter | Filter for =consult-buffer= | 895 | | consult-buffer-sources | List of virtual buffer sources | 896 | | consult-fd-args | Command line arguments for fd | 897 | | consult-find-args | Command line arguments for find | 898 | | consult-fontify-max-size | Buffers larger than this limit are not fontified | 899 | | consult-fontify-preserve | Preserve fontification for line-based commands. | 900 | | consult-git-grep-args | Command line arguments for git-grep | 901 | | consult-goto-line-numbers | Show line numbers for =consult-goto-line= | 902 | | consult-grep-max-columns | Maximal number of columns of the matching lines | 903 | | consult-grep-args | Command line arguments for grep | 904 | | consult-imenu-config | Mode-specific configuration for =consult-imenu= | 905 | | consult-line-numbers-widen | Show absolute line numbers when narrowing is active | 906 | | consult-line-start-from-top | Start the =consult-line= search from the top | 907 | | consult-locate-args | Command line arguments for locate | 908 | | consult-man-args | Command line arguments for man | 909 | | consult-mode-command-filter | Filter for =consult-mode-command= | 910 | | consult-mode-histories | Mode-specific history variables | 911 | | consult-narrow-key | Narrowing prefix key during completion | 912 | | consult-point-placement | Placement of the point when jumping to matches | 913 | | consult-preview-key | Keys which triggers preview | 914 | | consult-preview-allowed-hooks | List of hooks to allow during preview | 915 | | consult-preview-excluded-buffers | Predicate to exclude buffers from preview | 916 | | consult-preview-excluded-files | Regexps matched against file names during preview | 917 | | consult-preview-max-count | Maximum number of files to keep open during preview | 918 | | consult-preview-partial-size | Files larger than this size are previewed partially | 919 | | consult-preview-partial-chunk | Size of the file chunk which is previewed partially | 920 | | consult-preview-variables | Alist of variables to bind during preview | 921 | | consult-project-buffer-sources | List of virtual project buffer sources | 922 | | consult-project-function | Function which returns current project root | 923 | | consult-register-prefix | Prefix string for register keys during completion | 924 | | consult-ripgrep-args | Command line arguments for ripgrep | 925 | | consult-themes | List of themes to be presented for selection | 926 | | consult-widen-key | Widening key during completion | 927 | 928 | ** Project support 929 | :properties: 930 | :description: Project discovery support for search commands 931 | :custom_id: project-support 932 | :end: 933 | 934 | Multiple Consult search commands like =consult-grep= try to discover the current 935 | project and search in the project top level directory by default, if a project 936 | is found. Otherwise they fall back to the =default-directory=. By default, Consult 937 | uses the Emacs built-in project discovery support (=project-current= and 938 | =project-root=). It is possible to configure alternative methods via the 939 | customization variable =consult-project-function=. 940 | 941 | #+begin_src emacs-lisp 942 | ;; Optionally configure a different project root function. 943 | ;; 1. project.el (the default) 944 | (setq consult-project-function #'consult--default-project--function) 945 | ;; 2. vc.el (vc-root-dir) 946 | (setq consult-project-function (lambda (_) (vc-root-dir))) 947 | ;; 3. locate-dominating-file 948 | (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git"))) 949 | ;; 4. projectile.el (projectile-project-root) 950 | (autoload 'projectile-project-root "projectile") 951 | (setq consult-project-function (lambda (_) (projectile-project-root))) 952 | ;; 5. Disable project support 953 | (setq consult-project-function nil) 954 | #+end_src 955 | 956 | ** Fine-tuning of individual commands 957 | :properties: 958 | :alt_title: Fine-tuning 959 | :description: Fine-grained configuration for special requirements 960 | :end: 961 | 962 | *NOTE:* Consult supports fine-grained customization of individual commands. This 963 | configuration feature exists for experienced users with special requirements. 964 | There is the [[https://github.com/minad/consult/wiki][Consult wiki]], where we collect further configuration examples. 965 | 966 | Commands and buffer sources allow flexible, individual customization by using 967 | the =consult-customize= macro. You can override any option passed to the internal 968 | =consult--read= API. Note that since =consult--read= is part of the internal API, 969 | options could be removed, replaced or renamed in future versions of the package. 970 | 971 | Useful options are: 972 | - =:prompt= set the prompt string 973 | - =:preview-key= set the preview key, default is =consult-preview-key= 974 | - =:initial= set the initial input 975 | - =:initial-narrow= set the initial narrow key 976 | - =:default= set the default value 977 | - =:history= set the history variable symbol 978 | - =:add-history= add items to the future history, for example symbol at point 979 | - =:sort= enable or disable sorting 980 | - =:group= set to nil to disable candidate grouping and titles. 981 | - =:inherit-input-method= set to non-nil to inherit the input method. 982 | 983 | #+begin_src emacs-lisp 984 | (consult-customize 985 | ;; Disable preview for `consult-theme' completely. 986 | consult-theme :preview-key nil 987 | ;; Set preview for `consult-buffer' to key `M-.' 988 | consult-buffer :preview-key "M-." 989 | ;; For `consult-line' change the prompt and specify multiple preview 990 | ;; keybindings. Note that you should bind and in the 991 | ;; `minibuffer-local-completion-map' or `vertico-map' to the commands which 992 | ;; select the previous or next candidate. 993 | consult-line :prompt "Search: " 994 | :preview-key '("S-" "S-")) 995 | #+end_src 996 | 997 | The configuration values are evaluated at runtime, just before the completion 998 | session is started. Therefore you can use for example =thing-at-point= to adjust 999 | the initial input or the future history. 1000 | 1001 | #+begin_src emacs-lisp 1002 | (consult-customize 1003 | consult-line 1004 | :add-history (seq-some #'thing-at-point '(region symbol))) 1005 | 1006 | (defalias 'consult-line-thing-at-point 'consult-line) 1007 | 1008 | (consult-customize 1009 | consult-line-thing-at-point 1010 | :initial (thing-at-point 'symbol)) 1011 | #+end_src 1012 | 1013 | Generally it is possible to modify commands for your individual needs by the 1014 | following techniques: 1015 | 1016 | 1. Use =consult-customize= in order to change the command or source settings. 1017 | 2. Create your own wrapper function which passes modified arguments to the Consult functions. 1018 | 3. Create your own buffer [[#multiple-sources][multi sources]] for =consult-buffer=. 1019 | 4. Create advices to modify some internal behavior. 1020 | 5. Write or propose a patch. 1021 | 1022 | * Recommended packages 1023 | :properties: 1024 | :description: Related packages recommended for installation 1025 | :end: 1026 | 1027 | I use and recommend this combination of packages: 1028 | 1029 | - consult: This package 1030 | - [[https://github.com/minad/vertico][vertico]]: Fast and minimal vertical completion system 1031 | - [[https://github.com/minad/marginalia][marginalia]]: Annotations for the completion candidates 1032 | - [[https://github.com/oantolin/embark][embark and embark-consult]]: Action commands, which can act on the completion candidates 1033 | - [[https://github.com/oantolin/orderless][orderless]]: Completion style which offers flexible candidate filtering 1034 | - [[https://github.com/mhayashi1120/Emacs-wgrep][wgrep]] (or =grep-edit-mode= on Emacs 31): Editing of grep buffers. Use with 1035 | =consult-grep= via =embark-export=. 1036 | 1037 | There exist multiple fine completion UIs beside Vertico, which are supported by 1038 | Consult. Give them a try and find out which interaction model fits best for you. 1039 | 1040 | - The builtin completion UI, which pops up the =*Completions*= buffer. 1041 | - The builtin =icomplete-vertical-mode=. 1042 | - [[https://git.sr.ht/~protesilaos/mct][mct by Protesilaos Stavrou]]: Minibuffer and Completions in Tandem, which builds 1043 | on the default completion UI. 1044 | 1045 | Note that all packages are independent and can be exchanged with alternative 1046 | components, since there exist no hard dependencies. Furthermore it is possible 1047 | to get started with only default completion and Consult and add more components 1048 | later to the mix. For example you can omit Marginalia if you don't need 1049 | annotations. I highly recommend the Embark package, but in order to familiarize 1050 | yourself with the other components, you can first start without it - or you could 1051 | use with Embark right away and add the other components later on. 1052 | 1053 | We document a [[https://github.com/minad/consult/wiki/Auxiliary-packages][list of auxiliary packages]] in the Consult wiki. These packages 1054 | integrate Consult with special programs or with other packages in the wider 1055 | Emacs ecosystem. 1056 | 1057 | * Bug reports 1058 | :properties: 1059 | :description: How to create reproducible bug reports 1060 | :end: 1061 | 1062 | If you find a bug or suspect that there is a problem with Consult, please carry 1063 | out the following steps: 1064 | 1065 | 1. *Search through the issue tracker* if your issue has been reported before (and 1066 | has been resolved eventually) in the meantime. 1067 | 2. *Remove all packages involved in the suspected bug from your installation.* 1068 | 3. *Reinstall the newest version of all relevant packages*. Updating alone is not 1069 | sufficient, since package.el sometimes causes miscompilation. The list of 1070 | packages includes Consult, Compat, Vertico or other completion UIs, 1071 | Marginalia, Embark and Orderless. 1072 | 4. Either use the default completion UI or ensure that exactly one of 1073 | =vertico-mode=, =mct-mode=, or =icomplete-mode= is enabled. The unsupported modes 1074 | =selectrum-mode=, =ivy-mode=, =helm-mode=, =ido-mode= and =ido-ubiquitous-mode= must be 1075 | disabled. 1076 | 5. Ensure that the =completion-styles= variable is properly configured. Try to set 1077 | =completion-styles= to a list including =substring= or =orderless=. 1078 | 6. Try to reproduce the issue with the newest stable Emacs version. Start a bare 1079 | bone Emacs instance with =emacs -Q= on the command line. Execute the following 1080 | minimal code snippets in the scratch buffer. This way we can exclude side 1081 | effects due to configuration settings. If other packages are relevant to 1082 | reproduce the issue, include them in the minimal configuration snippet. 1083 | 1084 | Minimal setup with Vertico for =emacs -Q=: 1085 | #+begin_src emacs-lisp 1086 | (package-initialize) 1087 | (require 'consult) 1088 | (require 'vertico) 1089 | (vertico-mode) 1090 | (setq completion-styles '(substring basic)) 1091 | #+end_src 1092 | 1093 | Minimal setup with the default completion system for =emacs -Q=: 1094 | #+begin_src emacs-lisp 1095 | (package-initialize) 1096 | (require 'consult) 1097 | (setq completion-styles '(substring basic)) 1098 | #+end_src 1099 | 1100 | Please provide the necessary important information with your bug report: 1101 | 1102 | - The minimal configuration snippet used to reproduce the issue. 1103 | - Your completion UI (Default completion, Vertico, Mct or Icomplete). 1104 | - A stack trace in case the bug triggers an exception. 1105 | - Your Emacs version, since bugs may be fixed or introduced in newer versions. 1106 | - Your operating system, since Emacs behavior varies subtly between Linux, Mac 1107 | and Windows. 1108 | - The package manager, e.g., straight.el or package.el, used to install the 1109 | Emacs packages, in order to exclude update issues. Did you install Consult as 1110 | part of the Doom Emacs distribution? 1111 | - Do you use Evil? Consult does not provide Evil integration out of the box, but 1112 | there is some support in [[https://github.com/emacs-evil/evil-collection][evil-collection]]. 1113 | 1114 | When evaluating Consult-related code snippets you should enable [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical binding]]. 1115 | Consult often relies on lambdas and lexical closures. 1116 | 1117 | * Hacking 1118 | ** Creating asynchronous completion commands 1119 | 1120 | If you have a completion source that's both dynamic and expensive to generate, 1121 | =completing-read= may not be the best choice. Instead, =consult--read= serves as a 1122 | thin wrapper around =completing-read= that provides this functionality. For 1123 | example, consider the following slow script that splits its input on space: 1124 | 1125 | #+begin_src sh 1126 | #!/usr/bin/env bash 1127 | # simulate work 1128 | sleep .1 1129 | # generate completion candidates 1130 | printf "%s\n" "$*" | tr " " "\n" | sort 1131 | #+end_src 1132 | 1133 | Let's assume this script is callable as =testibus hello world=. To have Consult 1134 | use it for completion, use =consult--process-collection=: 1135 | 1136 | #+begin_src emacs-lisp 1137 | (consult--read 1138 | (consult--process-collection 1139 | (lambda (input) (list "testibus" (string-trim input)))) 1140 | :prompt "run testibus: ") 1141 | #+end_src 1142 | 1143 | If the completion candidates are generated by Lisp instead, use 1144 | =consult--dynamic-collection=: 1145 | 1146 | #+begin_src emacs-lisp 1147 | (consult--read 1148 | (consult--dynamic-collection 1149 | (lambda (input) 1150 | (sleep-for 0.1) ;; Simulate work 1151 | (split-string input nil t))) 1152 | :prompt "run testibus: ") 1153 | #+end_src 1154 | 1155 | =consult--dynamic-collection= can take a function with a callback such that the 1156 | completion UI can update for long running computations. 1157 | 1158 | #+begin_src emacs-lisp 1159 | (consult--read 1160 | (consult--dynamic-collection 1161 | (lambda (input callback) 1162 | (dotimes (i 3) 1163 | (sleep-for 0.1) ;; Simulate work 1164 | (funcall callback (mapcar (lambda (s) (format "%s%s" s i)) 1165 | (split-string input nil t)))))) 1166 | :prompt "run testibus: ") 1167 | #+end_src 1168 | 1169 | The asynchronous completion collections =consult--dynamic-collection= and 1170 | =consult--process-collection= can be used for =consult--multi= sources. Specify them 1171 | as =:async= field of the source plist. 1172 | 1173 | ** Live preview 1174 | 1175 | Implementing live preview requires the definition of a state or preview function 1176 | as defined by =consult--with-preview=. The preview function receives the candidate 1177 | and some action to perform (e.g., ='preview=). In its simplest form supporting 1178 | live preview, it looks something like this: 1179 | 1180 | #+begin_src emacs-lisp 1181 | (defun testibus--preview (action cand) 1182 | (pcase action 1183 | ('preview 1184 | (with-current-buffer-window " *testibus*" 'action nil 1185 | (erase-buffer) 1186 | (insert (format "input: %s\n" cand)))))) 1187 | #+end_src 1188 | 1189 | See the docstring of =consult--with-preview= for the lifecycle of the action 1190 | argument. Once defined, we can use this preview function in =consult--read=: 1191 | 1192 | #+begin_src emacs-lisp 1193 | (consult--read 1194 | (consult--dynamic-collection 1195 | (lambda (input callback) 1196 | (dotimes (i 3) 1197 | (sleep-for 0.1) ;; Simulate work 1198 | (funcall callback (mapcar (lambda (s) (format "%s%s" s i)) 1199 | (split-string input nil t)))))) 1200 | :prompt "run testibus: " 1201 | :state #'testibus--preview) 1202 | #+end_src 1203 | 1204 | * Contributions 1205 | :properties: 1206 | :description: Feature requests and pull requests 1207 | :end: 1208 | 1209 | Consult is a community effort, please participate in the discussions. 1210 | Contributions are welcome, but you may want to discuss potential contributions 1211 | first. Since this package is part of [[https://elpa.gnu.org/packages/consult.html][GNU ELPA]] contributions require a copyright 1212 | assignment to the FSF. 1213 | 1214 | If you have a proposal, take a look at the [[https://github.com/minad/consult/issues][Consult issue tracker]] and the [[https://github.com/minad/consult/issues/6][Consult 1215 | wishlist]]. There have been many prior feature discussions. Please search through 1216 | the issue tracker, maybe your issue or feature request has already been 1217 | discussed. You can contribute to the [[https://github.com/minad/consult/wiki][Consult wiki]], in case you want to share 1218 | small configuration or command snippets. 1219 | 1220 | * Acknowledgments 1221 | :properties: 1222 | :description: Contributors and Sources of Inspiration 1223 | :end: 1224 | 1225 | This package took inspiration from [[https://github.com/abo-abo/swiper#counsel][Counsel]] by Oleh Krehel. Some of the Consult 1226 | commands originated in the Counsel package or the wiki of the Selectrum package. 1227 | This package exists only thanks to the help of these great contributors and 1228 | thanks to the feedback of many users. Thank you! 1229 | 1230 | Code contributions: [[https://github.com/aagon][Aymeric Agon-Rambosson]], [[https://github.com/amosbird][Amos Bird]], [[https://github.com/ashton314][Ashton Wiersdorf]], [[https://github.com/aspiers/][Adam 1231 | Spiers]], [[https://github.com/astoff][Augusto Stoffel]], [[https://github.com/clemera/][Clemens Radermacher]], [[https://github.com/fuzy112][Zhengyi]], [[https://github.com/geolessel][Geoffrey Lessel]], [[https://github.com/iostapyshyn][Illia 1232 | Ostapyshyn]], [[https://github.com/jakanakaevangeli][jakanakaevangeli]], [[https://github.com/jdtsmith][JD Smith]], [[https://github.com/jyp][Jean-Philippe Bernardy]], [[https://github.com/mattiasdrp][mattiasdrp]], 1233 | [[https://github.com/mohamed-abdelnour][Mohamed Abdelnour]], [[https://github.com/mohkale][Mohsin Kaleem]], [[https://github.com/noctuid][Fox Kiester]], [[https://github.com/oantolin/][Omar Antolín Camarena]], [[https://github.com/okamsn/][Earl 1234 | Hyatt]], [[https://github.com/omar-polo][Omar Polo]], [[https://github.com/piotrkwiecinski][Piotr Kwiecinski]], [[https://github.com/rswgnu][Robert Weiner]], [[https://github.com/s-kostyaev/][Sergey Kostyaev]], [[https://github.com/scvalex][Alexandru 1235 | Scvorțov]], [[https://github.com/tecosaur][Tecosaur]], [[https://github.com/thisirs][Sylvain Rousseau]], [[https://github.com/tomfitzhenry/][Tom Fitzhenry]], [[https://hg.serna.eu][Iñigo Serna]] and [[https://github.com/akreisher][Alex 1236 | Kreisher]]. 1237 | 1238 | Advice and useful discussions: [[https://github.com/Qkessler][Enrique Kessler Martínez]], [[https://github.com/alphapapa/][Adam Porter]], [[https://github.com/bdarcus][Bruce 1239 | d'Arcus]], [[https://github.com/clemera/][Clemens Radermacher]], [[https://github.com/dgutov/][Dmitry Gutov]], [[https://github.com/hmelman/][Howard Melman]], [[https://github.com/iyefrat][Itai Y. Efrat]], [[https://github.com/jdtsmith][JD 1240 | Smith]], [[https://github.com/manuel-uberti/][Manuel Uberti]], [[https://github.com/monnier/][Stefan Monnier]], [[https://github.com/oantolin/][Omar Antolín Camarena]], [[https://github.com/purcell/][Steve Purcell]], 1241 | [[https://github.com/raxod502][Radon Rosborough]], [[https://github.com/tomfitzhenry/][Tom Fitzhenry]] and [[https://protesilaos.com][Protesilaos Stavrou]]. 1242 | 1243 | #+html: 1263 | -------------------------------------------------------------------------------- /consult-compile.el: -------------------------------------------------------------------------------- 1 | ;;; consult-compile.el --- Provides the command `consult-compile-error' -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides the command `consult-compile-error'. This is an extra 23 | ;; package, to allow lazy loading of compile.el. The 24 | ;; `consult-compile-error' command is autoloaded. 25 | 26 | ;;; Code: 27 | 28 | (require 'consult) 29 | (require 'compile) 30 | 31 | (defvar consult-compile--history nil) 32 | 33 | (defconst consult-compile--narrow 34 | '((?g . "Grep") 35 | (?e . "Error") 36 | (?w . "Warning") 37 | (?i . "Info"))) 38 | 39 | (defun consult-compile--font-lock (str) 40 | "Apply `font-lock' faces in STR, copy them to `face'." 41 | (let ((pos 0) (len (length str))) 42 | (while (< pos len) 43 | (let* ((face (get-text-property pos 'font-lock-face str)) 44 | (end (or (text-property-not-all pos len 'font-lock-face face str) len))) 45 | (put-text-property pos end 'face face str) 46 | (setq pos end))) 47 | str)) 48 | 49 | (defun consult-compile--error-candidates (buffer) 50 | "Return alist of errors and positions in BUFFER, a compilation buffer." 51 | (with-current-buffer buffer 52 | (let ((candidates) 53 | (grep (and (derived-mode-p 'grep-mode) ?g)) 54 | (pos (point-min))) 55 | (save-excursion 56 | (while (setq pos (compilation-next-single-property-change pos 'compilation-message)) 57 | (when-let* ((msg (get-text-property pos 'compilation-message)) 58 | ((compilation--message->loc msg))) 59 | (goto-char pos) 60 | (push (propertize 61 | (consult-compile--font-lock (consult--buffer-substring pos (pos-eol))) 62 | 'consult--type (or grep (pcase (compilation--message->type msg) 63 | (0 ?i) (1 ?w) (_ ?e))) 64 | 'consult--candidate (point-marker)) 65 | candidates)))) 66 | (nreverse candidates)))) 67 | 68 | (defun consult-compile--lookup (marker) 69 | "Lookup error position given error MARKER." 70 | (when-let (buffer (and marker (marker-buffer marker))) 71 | (with-current-buffer buffer 72 | (let ((next-error-highlight nil) 73 | (compilation-current-error marker) 74 | (overlay-arrow-position overlay-arrow-position)) 75 | (ignore-errors 76 | (save-window-excursion 77 | (compilation-next-error-function 0) 78 | (point-marker))))))) 79 | 80 | (defun consult-compile--compilation-buffers (file) 81 | "Return a list of compilation buffers relevant to FILE." 82 | (consult--buffer-query 83 | :sort 'alpha :predicate 84 | (lambda (buffer) 85 | (and (buffer-local-value 'compilation-locs buffer) 86 | (file-in-directory-p file (buffer-local-value 'default-directory buffer)))))) 87 | 88 | (defun consult-compile--state () 89 | "Like `consult--jump-state', also setting the current compilation error." 90 | (let ((jump (consult--jump-state))) 91 | (lambda (action marker) 92 | (let ((pos (consult-compile--lookup marker))) 93 | (when-let (buffer (and (eq action 'return) 94 | marker 95 | (marker-buffer marker))) 96 | (with-current-buffer buffer 97 | (setq compilation-current-error marker 98 | overlay-arrow-position marker))) 99 | (funcall jump action pos))))) 100 | 101 | ;;;###autoload 102 | (defun consult-compile-error (&optional arg) 103 | "Jump to a compilation error in the current buffer. 104 | 105 | This command collects entries from compilation buffers and grep buffers 106 | related to the current buffer. The command supports preview of the 107 | currently selected error. With prefix ARG, jump to the error message in 108 | the compilation buffer, instead of to the actual location of the error." 109 | (interactive "P") 110 | (consult--read 111 | (or (mapcan #'consult-compile--error-candidates 112 | (or (consult-compile--compilation-buffers 113 | default-directory) 114 | (user-error "No compilation buffers found for the current buffer"))) 115 | (user-error "No compilation errors found")) 116 | :prompt "Go to error: " 117 | :category 'consult-compile-error 118 | :sort nil 119 | :require-match t 120 | :history t ;; disable history 121 | :lookup #'consult--lookup-candidate 122 | :group (consult--type-group consult-compile--narrow) 123 | :narrow (consult--type-narrow consult-compile--narrow) 124 | :history '(:input consult-compile--history) 125 | :state (if arg (consult--jump-state) (consult-compile--state)))) 126 | 127 | (provide 'consult-compile) 128 | ;;; consult-compile.el ends here 129 | -------------------------------------------------------------------------------- /consult-flymake.el: -------------------------------------------------------------------------------- 1 | ;;; consult-flymake.el --- Provides the command `consult-flymake' -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides the command `consult-flymake'. This is an extra package, 23 | ;; to allow lazy loading of flymake.el. The `consult-flymake' command 24 | ;; is autoloaded. 25 | 26 | ;;; Code: 27 | 28 | (require 'consult) 29 | (require 'flymake) 30 | (eval-when-compile (require 'cl-lib)) 31 | 32 | (defconst consult-flymake--narrow 33 | '((?e . "Error") 34 | (?w . "Warning") 35 | (?n . "Note"))) 36 | 37 | (defun consult-flymake--candidates (diags) 38 | "Return Flymake errors from DIAGS as formatted candidates. 39 | DIAGS should be a list of diagnostics as returned from `flymake-diagnostics'." 40 | (let* ((diags 41 | (mapcar 42 | (lambda (diag) 43 | (let ((buffer (flymake-diagnostic-buffer diag)) 44 | (type (flymake-diagnostic-type diag))) 45 | (when (buffer-live-p buffer) 46 | (with-current-buffer buffer 47 | (save-excursion 48 | (without-restriction 49 | (goto-char (flymake-diagnostic-beg diag)) 50 | (list (buffer-name buffer) 51 | (line-number-at-pos) 52 | type 53 | (flymake-diagnostic-text diag) 54 | (point-marker) 55 | (flymake-diagnostic-end diag) 56 | (pcase (flymake--lookup-type-property type 'flymake-category) 57 | ('flymake-error ?e) 58 | ('flymake-warning ?w) 59 | (_ ?n))))))))) 60 | diags)) 61 | (diags (or (delq nil diags) 62 | (user-error "No flymake errors (Status: %s)" 63 | (if (seq-difference (flymake-running-backends) 64 | (flymake-reporting-backends)) 65 | 'running 'finished)))) 66 | (buffer-width (cl-loop for x in diags maximize (length (nth 0 x)))) 67 | (line-width (cl-loop for x in diags maximize (length (number-to-string (nth 1 x))))) 68 | (fmt (format "%%-%ds %%-%dd %%-7s %%s" buffer-width line-width))) 69 | (mapcar 70 | (pcase-lambda (`(,buffer ,line ,type ,text ,beg ,end ,narrow)) 71 | (propertize (format fmt buffer line 72 | (propertize (format "%s" (flymake--lookup-type-property 73 | type 'flymake-type-name type)) 74 | 'face (flymake--lookup-type-property 75 | type 'mode-line-face 'flymake-error)) 76 | text) 77 | 'consult--candidate (list beg (cons 0 (- end beg))) 78 | 'consult--type narrow)) 79 | ;; Sort by buffer, severity and position. 80 | (sort diags 81 | (pcase-lambda (`(,b1 _ ,t1 _ ,m1 _) `(,b2 _ ,t2 _ ,m2 _)) 82 | (let ((s1 (flymake--severity t1)) 83 | (s2 (flymake--severity t2))) 84 | (or 85 | (string-lessp b1 b2) 86 | (and (string-equal b1 b2) 87 | (or 88 | (> s1 s2) 89 | (and (= s1 s2) 90 | (< m1 m2))))))))))) 91 | 92 | ;;;###autoload 93 | (defun consult-flymake (&optional project) 94 | "Jump to Flymake diagnostic. 95 | When PROJECT is non-nil then prompt with diagnostics from all 96 | buffers in the current project instead of just the current buffer." 97 | (interactive "P") 98 | (consult--forbid-minibuffer) 99 | (consult--read 100 | (consult-flymake--candidates 101 | (if-let ((project (and project (project-current)))) 102 | (flymake--project-diagnostics project) 103 | (flymake-diagnostics))) 104 | :prompt "Flymake diagnostic: " 105 | :category 'consult-flymake-error 106 | :history t ;; disable history 107 | :require-match t 108 | :sort nil 109 | :group (consult--type-group consult-flymake--narrow) 110 | :narrow (consult--type-narrow consult-flymake--narrow) 111 | :lookup #'consult--lookup-candidate 112 | :state (consult--jump-state))) 113 | 114 | (provide 'consult-flymake) 115 | ;;; consult-flymake.el ends here 116 | -------------------------------------------------------------------------------- /consult-imenu.el: -------------------------------------------------------------------------------- 1 | ;;; consult-imenu.el --- Consult commands for imenu -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides imenu-related Consult commands. 23 | 24 | ;;; Code: 25 | 26 | (require 'consult) 27 | (require 'imenu) 28 | 29 | (defcustom consult-imenu-config 30 | '((emacs-lisp-mode :toplevel "Functions" 31 | :types ((?f "Functions" font-lock-function-name-face) 32 | (?m "Macros" font-lock-function-name-face) 33 | (?p "Packages" font-lock-constant-face) 34 | (?t "Types" font-lock-type-face) 35 | (?v "Variables" font-lock-variable-name-face)))) 36 | "Imenu configuration, faces and narrowing keys used by `consult-imenu'. 37 | 38 | For each type a narrowing key and a name must be specified. The 39 | face is optional. The imenu representation provided by the 40 | backend usually puts functions directly at the toplevel. 41 | `consult-imenu' moves them instead under the type specified by 42 | :toplevel." 43 | :type '(repeat (cons symbol plist)) 44 | :group 'consult) 45 | 46 | (defface consult-imenu-prefix 47 | '((t :inherit consult-key)) 48 | "Face used to highlight imenu prefix in `consult-imenu'." 49 | :group 'consult-faces) 50 | 51 | (defvar consult-imenu--history nil) 52 | (defvar-local consult-imenu--cache nil) 53 | 54 | (defun consult-imenu--switch-buffer (name pos buf fn &rest args) 55 | "Switch buffer before invoking special menu items. 56 | NAME is the item name. 57 | POS is the position. 58 | BUF is the buffer. 59 | FN is the original special item function. 60 | ARGS are the arguments to the special item function." 61 | (funcall consult--buffer-display buf) 62 | (apply fn name pos args)) 63 | 64 | (defun consult-imenu--normalize (pos) 65 | "Return normalized imenu POS." 66 | (pcase pos 67 | ;; Create marker from integer item 68 | ((pred integerp) (setq pos (copy-marker pos))) 69 | ;; Semantic uses overlay for positions 70 | ((pred overlayp) (setq pos (copy-marker (overlay-start pos)))) 71 | ;; Wrap special item 72 | (`(,pos ,fn . ,args) 73 | (setq pos `(,pos ,#'consult-imenu--switch-buffer ,(current-buffer) 74 | ,fn ,@args)))) 75 | (if (or (consp pos) 76 | (eq imenu-default-goto-function #'imenu-default-goto-function)) 77 | pos 78 | (list pos #'consult-imenu--switch-buffer (current-buffer) 79 | imenu-default-goto-function))) 80 | 81 | (defun consult-imenu--flatten (prefix face list types) 82 | "Flatten imenu LIST. 83 | PREFIX is prepended in front of all items. 84 | FACE is the item face. 85 | TYPES is the mode-specific types configuration." 86 | (mapcan 87 | (lambda (item) 88 | (if (imenu--subalist-p item) 89 | (let* ((name (concat (car item))) 90 | (next-prefix name) 91 | (next-face face)) 92 | (add-face-text-property 0 (length name) 93 | 'consult-imenu-prefix 'append name) 94 | (if prefix 95 | (setq next-prefix (concat prefix "/" name)) 96 | (when-let (type (cdr (assoc name types))) 97 | (put-text-property 0 (length name) 'consult--type (car type) name) 98 | (setq next-face (cadr type)))) 99 | (consult-imenu--flatten next-prefix next-face (cdr item) types)) 100 | (list (cons 101 | (if prefix 102 | (let ((key (concat prefix " " (car item)))) 103 | (add-face-text-property (1+ (length prefix)) (length key) 104 | face 'append key) 105 | key) 106 | (car item)) 107 | (consult-imenu--normalize (cdr item)))))) 108 | list)) 109 | 110 | (defun consult-imenu--compute () 111 | "Compute imenu candidates." 112 | (consult--forbid-minibuffer) 113 | (let* ((imenu-use-markers t) 114 | ;; Generate imenu, see `imenu--make-index-alist'. 115 | (items (imenu--truncate-items 116 | (save-excursion 117 | (without-restriction 118 | (funcall imenu-create-index-function))))) 119 | (config (cdr (seq-find (lambda (x) (derived-mode-p (car x))) consult-imenu-config)))) 120 | ;; Fix toplevel items, e.g., emacs-lisp-mode toplevel items are functions 121 | (when-let (toplevel (plist-get config :toplevel)) 122 | (let ((tops (seq-remove (lambda (x) (listp (cdr x))) items)) 123 | (rest (seq-filter (lambda (x) (listp (cdr x))) items))) 124 | (setq items (nconc rest (and tops (list (cons toplevel tops))))))) 125 | ;; Apply our flattening in order to ease searching the imenu. 126 | (consult-imenu--flatten 127 | nil nil items 128 | (mapcar (pcase-lambda (`(,x ,y ,z)) (list y x z)) 129 | (plist-get config :types))))) 130 | 131 | (defun consult-imenu--deduplicate (items) 132 | "Deduplicate imenu ITEMS by appending a counter." 133 | ;; Some imenu backends generate duplicate items (e.g. for overloaded methods in java) 134 | (let ((ht (make-hash-table :test #'equal :size (length items)))) 135 | (dolist (item items) 136 | (if-let (count (gethash (car item) ht)) 137 | (setcar item (format "%s (%s)" (car item) 138 | (puthash (car item) (1+ count) ht))) 139 | (puthash (car item) 0 ht))))) 140 | 141 | (defun consult-imenu--items () 142 | "Return cached imenu candidates, may error." 143 | (unless (equal (car consult-imenu--cache) (buffer-modified-tick)) 144 | (setq consult-imenu--cache (cons (buffer-modified-tick) (consult-imenu--compute)))) 145 | (cdr consult-imenu--cache)) 146 | 147 | (defun consult-imenu--items-safe () 148 | "Return cached imenu candidates, will not error." 149 | (condition-case err 150 | (consult-imenu--items) 151 | (t (message "Cannot create Imenu for buffer %s (%s)" 152 | (buffer-name) (error-message-string err)) 153 | nil))) 154 | 155 | (defun consult-imenu--multi-items (buffers) 156 | "Return all imenu items from BUFFERS." 157 | (consult--with-increased-gc 158 | (let ((reporter (make-progress-reporter "Collecting" 0 (length buffers)))) 159 | (prog1 160 | (apply #'append 161 | (seq-map-indexed (lambda (buf idx) 162 | (with-current-buffer buf 163 | (prog1 (consult-imenu--items-safe) 164 | (progress-reporter-update 165 | reporter (1+ idx) (buffer-name))))) 166 | buffers)) 167 | (progress-reporter-done reporter))))) 168 | 169 | (defun consult-imenu--jump (item) 170 | "Jump to imenu ITEM via `consult--jump'. 171 | In contrast to the builtin `imenu' jump function, 172 | this function can jump across buffers." 173 | (pcase item 174 | (`(,name ,pos ,fn . ,args) 175 | (push-mark nil t) 176 | (apply fn name pos args)) 177 | (`(,_ . ,pos) 178 | (consult--jump pos)) 179 | (_ (error "Unknown imenu item: %S" item))) 180 | (run-hooks 'imenu-after-jump-hook)) 181 | 182 | (defun consult-imenu--narrow () 183 | "Return narrowing configuration for the current buffer." 184 | (mapcar (lambda (x) (cons (car x) (cadr x))) 185 | (plist-get (cdr (seq-find (lambda (x) (derived-mode-p (car x))) 186 | consult-imenu-config)) 187 | :types))) 188 | 189 | (defun consult-imenu--group () 190 | "Create a imenu group function for the current buffer." 191 | (when-let (narrow (consult-imenu--narrow)) 192 | (lambda (cand transform) 193 | (let ((type (get-text-property 0 'consult--type cand))) 194 | (cond 195 | ((and transform type) 196 | (substring cand (1+ (next-single-property-change 0 'consult--type cand)))) 197 | (transform cand) 198 | (type (alist-get type narrow))))))) 199 | 200 | (defun consult-imenu--select (prompt items) 201 | "Select from imenu ITEMS given PROMPT string." 202 | (consult-imenu--deduplicate items) 203 | (consult-imenu--jump 204 | (consult--read 205 | (or items (user-error "Imenu is empty")) 206 | :state 207 | (let ((preview (consult--jump-preview))) 208 | (lambda (action cand) 209 | ;; Only preview simple menu items which are markers, 210 | ;; in order to avoid any bad side effects. 211 | (funcall preview action (and (markerp (cdr cand)) (cdr cand))))) 212 | :narrow 213 | (when-let (narrow (consult-imenu--narrow)) 214 | (list :predicate 215 | (lambda (cand) 216 | (eq (get-text-property 0 'consult--type (car cand)) consult--narrow)) 217 | :keys narrow)) 218 | :group (consult-imenu--group) 219 | :prompt prompt 220 | :require-match t 221 | :category 'imenu 222 | :lookup #'consult--lookup-cons 223 | :history 'consult-imenu--history 224 | :add-history (thing-at-point 'symbol) 225 | :sort nil))) 226 | 227 | ;;;###autoload 228 | (defun consult-imenu () 229 | "Select item from flattened `imenu' using `completing-read' with preview. 230 | 231 | The command supports preview and narrowing. See the variable 232 | `consult-imenu-config', which configures the narrowing. 233 | The symbol at point is added to the future history. 234 | 235 | See also `consult-imenu-multi'." 236 | (interactive) 237 | (consult-imenu--select 238 | "Go to item: " 239 | (consult--slow-operation "Building Imenu..." 240 | (consult-imenu--items)))) 241 | 242 | ;;;###autoload 243 | (defun consult-imenu-multi (&optional query) 244 | "Select item from the imenus of all buffers from the same project. 245 | 246 | In order to determine the buffers belonging to the same project, the 247 | `consult-project-function' is used. Only the buffers with the 248 | same major mode as the current buffer are used. See also 249 | `consult-imenu' for more details. In order to search a subset of buffers, 250 | QUERY can be set to a plist according to `consult--buffer-query'." 251 | (interactive "P") 252 | (unless (keywordp (car-safe query)) 253 | (setq query (list :sort 'alpha :mode major-mode 254 | :directory (and (not query) 'project)))) 255 | (let ((buffers (consult--buffer-query-prompt "Go to item" query))) 256 | (consult-imenu--select (car buffers) 257 | (consult-imenu--multi-items (cdr buffers))))) 258 | 259 | (provide 'consult-imenu) 260 | ;;; consult-imenu.el ends here 261 | -------------------------------------------------------------------------------- /consult-info.el: -------------------------------------------------------------------------------- 1 | ;;; consult-info.el --- Search through the info manuals -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides the command `consult-info'. This is an extra package, 23 | ;; to allow lazy loading of info.el. The `consult-info' command 24 | ;; is autoloaded. 25 | 26 | ;;; Code: 27 | 28 | (require 'consult) 29 | (require 'info) 30 | (eval-when-compile (require 'cl-lib)) 31 | 32 | (defvar-local consult-info--manual nil) 33 | (defvar consult-info--history nil) 34 | 35 | (defun consult-info--candidates (buffers input callback) 36 | "Collect matching candidates from info buffers. 37 | INPUT is the user input which should be matched. 38 | BUFFERS is the list of buffers. 39 | CALLBACK receives the candidates." 40 | (pcase-let* ((`(,regexps . ,hl) (consult--compile-regexp input 'emacs t)) 41 | (re (concat "\\(\^_\n\\(?:.*Node:[ \t]*\\([^,\t\n]+\\)\\)?.*\n\\)\\|" (car regexps))) 42 | (candidates nil) 43 | (cand-idx 0) 44 | (last-node nil) 45 | (full-node nil)) 46 | (when regexps 47 | (dolist (buf buffers) 48 | (with-current-buffer buf 49 | (setq last-node nil full-node nil) 50 | (widen) 51 | (goto-char (point-min)) 52 | (while (and (not (eobp)) (re-search-forward re nil t)) 53 | (if (match-end 1) 54 | (progn 55 | (if-let ((node (match-string 2))) 56 | (unless (equal node last-node) 57 | (setq full-node (concat consult-info--manual node) 58 | last-node node)) 59 | (setq last-node nil full-node nil)) 60 | (goto-char (1+ (pos-eol)))) 61 | (let ((bol (pos-bol)) 62 | (eol (pos-eol))) 63 | (goto-char bol) 64 | (when (and 65 | full-node 66 | ;; Information separator character 67 | (>= (- (point) 2) (point-min)) 68 | (not (eq (char-after (- (point) 2)) ?\^_)) 69 | ;; Non-blank line, only printable characters on the line. 70 | (not (looking-at-p "^\\s-*$")) 71 | (looking-at-p "^[[:print:]]*$") 72 | ;; Matches all regexps 73 | (cl-loop for r in (cdr regexps) always 74 | (progn 75 | (goto-char bol) 76 | (re-search-forward r eol t)))) 77 | (let ((cand (concat 78 | (funcall hl (buffer-substring-no-properties bol eol)) 79 | (consult--tofu-encode cand-idx)))) 80 | (put-text-property 0 1 'consult--info (list full-node bol buf) cand) 81 | (cl-incf cand-idx) 82 | (push cand candidates))) 83 | (goto-char (1+ eol)))))) 84 | (funcall callback (nreverse candidates)) 85 | (setq candidates nil))))) 86 | 87 | (defun consult-info--position (cand) 88 | "Return position information for CAND." 89 | (when-let ((pos (and cand (get-text-property 0 'consult--info cand))) 90 | (matches (consult--point-placement cand 0)) 91 | (dest (+ (cadr pos) (car matches)))) 92 | `( ,(cdr matches) ,dest . ,pos))) 93 | 94 | (defun consult-info--action (cand) 95 | "Jump to info CAND." 96 | (pcase (consult-info--position cand) 97 | (`( ,_matches ,pos ,node ,_bol ,_buf) 98 | (info node) 99 | (widen) 100 | (goto-char pos) 101 | (Info-select-node) 102 | (run-hooks 'consult-after-jump-hook)))) 103 | 104 | (defun consult-info--state () 105 | "Info manual preview state." 106 | (let ((preview (consult--jump-preview))) 107 | (lambda (action cand) 108 | (pcase action 109 | ('preview 110 | (setq cand (consult-info--position cand)) 111 | (funcall preview 'preview 112 | (pcase cand 113 | (`(,matches ,pos ,_node ,_bol ,buf) 114 | (cons (set-marker (make-marker) pos buf) matches)))) 115 | (let (Info-history Info-history-list Info-history-forward) 116 | (when cand (ignore-errors (Info-select-node))))) 117 | ('return 118 | (consult-info--action cand)))))) 119 | 120 | (defun consult-info--group (cand transform) 121 | "Return title for CAND or TRANSFORM the candidate." 122 | (if transform cand 123 | (car (get-text-property 0 'consult--info cand)))) 124 | 125 | (defun consult-info--buffer (manual init) 126 | "Make preview buffer for MANUAL and call INIT." 127 | (let (buf) 128 | (unwind-protect 129 | (with-current-buffer (setq buf (generate-new-buffer 130 | (format "*info-%s*" manual))) 131 | (let (Info-history Info-history-list Info-history-forward) 132 | (Info-mode) 133 | (Info-find-node manual "Top") 134 | (setq consult-info--manual (concat "(" manual ")")) 135 | (and (ignore-errors (funcall init)) 136 | (prog1 buf 137 | (consult--preview-rename-buffer buf) 138 | (setq buf nil))))) 139 | (when buf (kill-buffer buf))))) 140 | 141 | (defun consult-info--prepare-buffers (manuals fun) 142 | "Prepare buffers for MANUALS and call FUN with buffers." 143 | (declare (indent 1)) 144 | (let (buffers) 145 | (unwind-protect 146 | (let ((reporter (make-progress-reporter "Preparing" 0 (length manuals)))) 147 | (consult--with-increased-gc 148 | (cl-loop 149 | for idx from 0 for manual in manuals do 150 | (push (consult-info--buffer manual #'always) buffers) 151 | ;; Create a separate buffer if the info manual has subfiles. They 152 | ;; are present on my system and have names like 153 | ;; /usr/share/info/texinfo.info-2.gz. 154 | (while-let 155 | ((sub (buffer-local-value 'Info-current-subfile (car buffers))) 156 | (pos (string-match-p "-\\([0-9]+\\)\\'" sub)) 157 | (buf (consult-info--buffer 158 | manual 159 | (lambda () 160 | (ignore-errors 161 | (Info-read-subfile 162 | (format "%s%s" (substring sub 0 pos) 163 | (1- (string-to-number (substring sub pos))))) 164 | (Info-select-node) 165 | t))))) 166 | (push buf buffers)) 167 | (progress-reporter-update reporter (1+ idx) manual))) 168 | (progress-reporter-done reporter) 169 | (funcall fun (reverse buffers))) 170 | (mapc #'kill-buffer buffers)))) 171 | 172 | ;;;###autoload 173 | (defun consult-info (&rest manuals) 174 | "Full text search through info MANUALS." 175 | (interactive 176 | (if Info-current-file 177 | (list (file-name-base Info-current-file)) 178 | (info-initialize) 179 | (completing-read-multiple 180 | "Info Manuals: " 181 | (info--manual-names current-prefix-arg) 182 | nil t))) 183 | (consult-info--prepare-buffers manuals 184 | (lambda (buffers) 185 | (consult--read 186 | (consult--dynamic-collection 187 | (apply-partially #'consult-info--candidates buffers)) 188 | :state (consult-info--state) 189 | :prompt 190 | (format "Info (%s): " 191 | (string-join (if (length> manuals 3) 192 | `(,@(seq-take manuals 3) ,"…") 193 | manuals) 194 | ", ")) 195 | :require-match t 196 | :sort nil 197 | :category 'consult-info 198 | :history '(:input consult-info--history) 199 | :group #'consult-info--group 200 | :add-history (thing-at-point 'symbol) 201 | :lookup #'consult--lookup-member)))) 202 | 203 | ;;;###autoload 204 | (progn ;; Wrapped with `progn' to preload `consult-info-define'. 205 | (defun consult-info-define (name &rest manuals) 206 | "Define `consult-info-NAME' command to search through MANUALS. 207 | MANUALS is a list of a strings. NAME can be a symbol or a string. If 208 | NAME is a string, it is added to the MANUALS list. Return name of 209 | defined command as symbol." 210 | (let ((cmd (intern (format "consult-info-%s" name)))) 211 | (when (stringp name) (push name manuals)) 212 | (defalias cmd (lambda () (interactive) (apply #'consult-info manuals)) 213 | (format "Search via `consult-info' through the manual%s %s:\n\n%s" 214 | (if (cdr manuals) "s" "") 215 | (mapconcat (lambda (m) (format "\"%s\"" m)) manuals ", ") 216 | (mapconcat (lambda (m) (format " * Info node `(%s)'" m)) manuals "\n"))) 217 | cmd))) 218 | 219 | (provide 'consult-info) 220 | ;;; consult-info.el ends here 221 | -------------------------------------------------------------------------------- /consult-kmacro.el: -------------------------------------------------------------------------------- 1 | ;;; consult-kmacro.el --- Provides the command `consult-kmacro' -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides the command `consult-kmacro'. This is an extra package, 23 | ;; to allow lazy loading of kmacro.el. The `consult-kmacro' command 24 | ;; is autoloaded. 25 | 26 | ;;; Code: 27 | 28 | (require 'consult) 29 | (require 'kmacro) 30 | (eval-when-compile (require 'subr-x)) 31 | 32 | (defvar consult-kmacro--history nil) 33 | 34 | (defun consult-kmacro--candidates () 35 | "Return alist of kmacros and indices." 36 | (thread-last 37 | ;; List of macros 38 | (append (and last-kbd-macro (list (kmacro-ring-head))) kmacro-ring) 39 | ;; Emacs 29 uses OClosures. I like OClosures but it would have been better 40 | ;; if public APIs wouldn't change like that. 41 | (mapcar (lambda (x) 42 | (static-if (> emacs-major-version 28) 43 | (list (kmacro--keys x) (kmacro--counter x) (kmacro--format x) x) 44 | `(,@x ,x)))) 45 | ;; Filter mouse clicks 46 | (seq-remove (lambda (x) (seq-some #'mouse-event-p (car x)))) 47 | ;; Format macros 48 | (mapcar (pcase-lambda (`(,keys ,counter ,format ,km)) 49 | (propertize 50 | (format-kbd-macro keys 1) 51 | 'consult--candidate km 52 | 'consult-kmacro--annotation 53 | ;; If the counter is 0 and the counter format is its default, 54 | ;; then there is a good chance that the counter isn't actually 55 | ;; being used. This can only be wrong when a user 56 | ;; intentionally starts the counter with a negative value and 57 | ;; then increments it to 0. 58 | (cond 59 | ((not (equal format "%d")) ;; show counter for non-default format 60 | (format " (counter=%d, format=%s) " counter format)) 61 | ((/= counter 0) ;; show counter if non-zero 62 | (format " (counter=%d)" counter)))))) 63 | (delete-dups))) 64 | 65 | ;;;###autoload 66 | (defun consult-kmacro (arg) 67 | "Run a chosen keyboard macro. 68 | 69 | With prefix ARG, run the macro that many times. 70 | Macros containing mouse clicks are omitted." 71 | (interactive "p") 72 | (let ((km (consult--read 73 | (or (consult-kmacro--candidates) 74 | (user-error "No keyboard macros defined")) 75 | :prompt "Keyboard macro: " 76 | :category 'consult-kmacro 77 | :require-match t 78 | :sort nil 79 | :history 'consult-kmacro--history 80 | :annotate 81 | (lambda (cand) 82 | (get-text-property 0 'consult-kmacro--annotation cand)) 83 | :lookup #'consult--lookup-candidate))) 84 | ;; Kmacros are lambdas (oclosures) on Emacs 29 85 | (funcall (static-if (> emacs-major-version 28) 86 | km 87 | (kmacro-lambda-form km)) 88 | arg))) 89 | 90 | (provide 'consult-kmacro) 91 | ;;; consult-kmacro.el ends here 92 | -------------------------------------------------------------------------------- /consult-org.el: -------------------------------------------------------------------------------- 1 | ;;; consult-org.el --- Consult commands for org-mode -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides a `completing-read' interface for Org mode navigation. 23 | ;; This is an extra package, to allow lazy loading of Org. 24 | 25 | ;;; Code: 26 | 27 | (require 'consult) 28 | (require 'org) 29 | 30 | (defvar consult-org--history nil) 31 | 32 | (defun consult-org--narrow () 33 | "Narrowing configuration for `consult-org' commands." 34 | (let ((todo-kws 35 | (seq-filter 36 | (lambda (x) (<= ?a (car x) ?z)) 37 | (mapcar (lambda (s) 38 | (pcase-let ((`(,a ,b) (split-string s "("))) 39 | (cons (downcase (string-to-char (or b a))) a))) 40 | (apply #'append (mapcar #'cdr org-todo-keywords)))))) 41 | (list :predicate 42 | (lambda (cand) 43 | (pcase-let ((`(,level ,todo ,prio . ,_) 44 | (get-text-property 0 'consult-org--heading cand))) 45 | (cond 46 | ((<= ?1 consult--narrow ?9) (<= level (- consult--narrow ?0))) 47 | ((<= ?A consult--narrow ?Z) (eq prio consult--narrow)) 48 | (t (equal todo (alist-get consult--narrow todo-kws)))))) 49 | :keys 50 | (nconc (mapcar (lambda (c) (cons c (format "Level %c" c))) 51 | (number-sequence ?1 ?9)) 52 | (mapcar (lambda (c) (cons c (format "Priority %c" c))) 53 | (number-sequence (max ?A org-highest-priority) 54 | (min ?Z org-lowest-priority))) 55 | todo-kws)))) 56 | 57 | (defun consult-org--headings (prefix match scope &rest skip) 58 | "Return a list of Org heading candidates. 59 | 60 | If PREFIX is non-nil, prefix the candidates with the buffer name. 61 | MATCH, SCOPE and SKIP are as in `org-map-entries'." 62 | (let (buffer (idx 0)) 63 | (apply 64 | #'org-map-entries 65 | (lambda () 66 | ;; Reset the cache when the buffer changes, since `org-get-outline-path' uses the cache 67 | (unless (eq buffer (buffer-name)) 68 | (setq buffer (buffer-name) 69 | org-outline-path-cache nil)) 70 | (pcase-let* ((`(_ ,level ,todo ,prio ,_hl ,tags) (org-heading-components)) 71 | (tags (if org-use-tag-inheritance 72 | (when-let ((tags (org-get-tags))) 73 | (concat ":" (string-join tags ":") ":")) 74 | tags)) 75 | (cand (org-format-outline-path 76 | (org-get-outline-path 'with-self 'use-cache) 77 | most-positive-fixnum))) 78 | (when todo 79 | (put-text-property 0 (length todo) 'face (org-get-todo-face todo) todo)) 80 | (when tags 81 | (put-text-property 0 (length tags) 'face 'org-tag tags)) 82 | (setq cand (concat (and prefix buffer) (and prefix " ") cand (and tags " ") 83 | tags (consult--tofu-encode idx))) 84 | (cl-incf idx) 85 | (add-text-properties 0 1 86 | `(org-marker ,(point-marker) 87 | consult-org--heading (,level ,todo ,prio . ,buffer)) 88 | cand) 89 | cand)) 90 | match scope skip))) 91 | 92 | (defun consult-org--annotate (cand) 93 | "Annotate CAND for `consult-org-heading'." 94 | (pcase-let ((`(,_level ,todo ,prio . ,_) 95 | (get-text-property 0 'consult-org--heading cand))) 96 | (consult--annotate-align 97 | cand 98 | (concat todo 99 | (and prio (format #(" [#%c]" 1 6 (face org-priority)) prio)))))) 100 | 101 | (defun consult-org--group (cand transform) 102 | "Return title for CAND or TRANSFORM the candidate." 103 | (pcase-let ((`(,_level ,_todo ,_prio . ,buffer) 104 | (get-text-property 0 'consult-org--heading cand))) 105 | (if transform (substring cand (1+ (length buffer))) buffer))) 106 | 107 | ;;;###autoload 108 | (defun consult-org-heading (&optional match scope) 109 | "Jump to an Org heading. 110 | 111 | MATCH and SCOPE are as in `org-map-entries' and determine which 112 | entries are offered. By default, all entries of the current 113 | buffer are offered." 114 | (interactive (unless (derived-mode-p #'org-mode) 115 | (user-error "Must be called from an Org buffer"))) 116 | (let ((prefix (not (memq scope '(nil tree region region-start-level file))))) 117 | (consult--read 118 | (consult--slow-operation "Collecting headings..." 119 | (or (consult-org--headings prefix match scope) 120 | (user-error "No headings"))) 121 | :prompt "Go to heading: " 122 | :category 'org-heading 123 | :sort nil 124 | :require-match t 125 | :history '(:input consult-org--history) 126 | :narrow (consult-org--narrow) 127 | :state (consult--jump-state) 128 | :annotate #'consult-org--annotate 129 | :group (and prefix #'consult-org--group) 130 | :lookup (apply-partially #'consult--lookup-prop 'org-marker)))) 131 | 132 | ;;;###autoload 133 | (defun consult-org-agenda (&optional match) 134 | "Jump to an Org agenda heading. 135 | 136 | By default, all agenda entries are offered. MATCH is as in 137 | `org-map-entries' and can used to refine this." 138 | (interactive) 139 | (unless org-agenda-files 140 | (user-error "No agenda files")) 141 | (consult-org-heading match 'agenda)) 142 | 143 | (provide 'consult-org) 144 | ;;; consult-org.el ends here 145 | -------------------------------------------------------------------------------- /consult-register.el: -------------------------------------------------------------------------------- 1 | ;;; consult-register.el --- Consult commands for registers -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides register-related Consult commands. 23 | 24 | ;;; Code: 25 | 26 | (require 'consult) 27 | (require 'kmacro) 28 | 29 | (defcustom consult-register-prefix #("#" 0 1 (face consult-key)) 30 | "Prepend prefix in front of register keys during completion." 31 | :type '(choice (const nil) string) 32 | :group 'consult) 33 | 34 | (defvar consult-register--narrow 35 | '((?n . "Number") 36 | (?s . "String") 37 | (?p . "Point") 38 | (?r . "Rectangle") 39 | (?t . "Frameset") 40 | (?k . "Kmacro") 41 | (?f . "File") 42 | (?b . "Buffer") 43 | (?w . "Window")) 44 | "Register type names. 45 | Each element of the list must have the form (char . name).") 46 | 47 | (cl-defun consult-register--format-value (val) 48 | "Format generic register VAL as string." 49 | (with-output-to-string (register-val-describe val nil))) 50 | 51 | (cl-defgeneric consult-register--describe (val) 52 | "Describe generic register VAL." 53 | (list (consult-register--format-value val))) 54 | 55 | (cl-defmethod consult-register--describe ((val number)) 56 | "Describe numeric register VAL." 57 | (list (consult-register--format-value val) 'consult--type ?n)) 58 | 59 | (cl-defmethod consult-register--describe ((val string)) 60 | "Describe string register VAL." 61 | (list val 'consult--type 62 | (if (eq (car (get-text-property 0 'yank-handler val)) 63 | 'rectangle--insert-for-yank) 64 | ?r ?s))) 65 | 66 | (cl-defmethod consult-register--describe ((val marker)) 67 | "Describe marker register VAL." 68 | (with-current-buffer (marker-buffer val) 69 | (save-excursion 70 | (without-restriction 71 | (goto-char val) 72 | (let* ((line (line-number-at-pos)) 73 | (str (propertize (consult--line-with-mark val) 74 | 'consult-location (cons val line)))) 75 | (list (consult--format-file-line-match (buffer-name) line str) 76 | 'multi-category `(consult-location . ,str) 77 | 'consult--type ?p)))))) 78 | 79 | (defmacro consult-register--describe-kmacro () 80 | "Generate method which describes kmacro register." 81 | `(cl-defmethod consult-register--describe ((val ,(if (< emacs-major-version 30) 'kmacro-register 'kmacro))) 82 | (list (consult-register--format-value val) 'consult--type ?k))) 83 | (consult-register--describe-kmacro) 84 | 85 | (cl-defmethod consult-register--describe ((val (head file))) 86 | "Describe file register VAL." 87 | (list (propertize (abbreviate-file-name (cdr val)) 'face 'consult-file) 88 | 'consult--type ?f 'multi-category `(file . ,(cdr val)))) 89 | 90 | (cl-defmethod consult-register--describe ((val (head buffer))) 91 | "Describe buffer register VAL." 92 | (list (propertize (cdr val) 'face 'consult-buffer) 93 | 'consult--type ?f 'multi-category `(buffer . ,(cdr val)))) 94 | 95 | (cl-defmethod consult-register--describe ((val (head file-query))) 96 | "Describe file-query register VAL." 97 | (list (format "%s at position %d" 98 | (propertize (abbreviate-file-name (cadr val)) 99 | 'face 'consult-file) 100 | (caddr val)) 101 | 'consult--type ?f 'multi-category `(file . ,(cadr val)))) 102 | 103 | (cl-defmethod consult-register--describe ((val cons)) 104 | "Describe rectangle or window-configuration register VAL." 105 | (cond 106 | ((stringp (car val)) 107 | (list (string-join val "\n") 'consult--type ?r)) 108 | ((window-configuration-p (car val)) 109 | (list (consult-register--format-value val) 110 | 'consult--type ?w)) 111 | (t (list (consult-register--format-value val))))) 112 | 113 | (with-eval-after-load 'frameset 114 | (cl-defmethod consult-register--describe ((val frameset-register)) 115 | "Describe frameset register VAL." 116 | (list (consult-register--format-value val) 'consult--type ?t))) 117 | 118 | ;;;###autoload 119 | (defun consult-register-window (buffer &optional show-empty pred) 120 | "Enhanced drop-in replacement for `register-preview'. 121 | 122 | BUFFER is the window buffer. 123 | SHOW-EMPTY must be t if the window should be shown for an empty register list. 124 | Optional argument PRED specifies the types of register to show." 125 | (let ((regs (consult-register--alist 'noerror pred)) 126 | (separator 127 | (and (display-graphic-p) 128 | (propertize #(" \n" 0 1 (display (space :align-to right))) 129 | 'face '(:inherit consult-separator :height 1 :underline t))))) 130 | (when (or show-empty regs) 131 | (with-current-buffer-window buffer 132 | (cons 'display-buffer-at-bottom 133 | '((window-height . fit-window-to-buffer) 134 | (preserve-size . (nil . t)))) 135 | nil 136 | (setq-local cursor-in-non-selected-windows nil 137 | mode-line-format nil 138 | truncate-lines t 139 | window-min-height 1 140 | window-resize-pixelwise t 141 | scroll-margin 0) 142 | (insert (mapconcat 143 | (lambda (reg) 144 | (concat (consult-register-format reg) separator)) 145 | regs nil)))))) 146 | 147 | ;;;###autoload 148 | (defun consult-register-format (reg &optional completion) 149 | "Enhanced preview of register REG. 150 | This function can be used as `register-preview-function'. 151 | If COMPLETION is non-nil format the register for completion." 152 | (pcase-let* ((`(,key . ,val) reg) 153 | (key-str (propertize (single-key-description key) 'face 'consult-key)) 154 | (key-len (max 3 (length key-str))) 155 | (`(,str . ,props) (consult-register--describe val))) 156 | (when (string-search "\n" str) 157 | (let* ((lines (seq-take (seq-remove #'string-blank-p (split-string str "\n")) 3)) 158 | (space (cl-loop for x in lines minimize (string-match-p "[^ ]" x)))) 159 | (setq str (mapconcat (lambda (x) (substring x space)) 160 | lines (concat "\n" (make-string (1+ key-len) ?\s)))))) 161 | (setq str (concat 162 | (and completion consult-register-prefix) 163 | key-str (make-string (- key-len (length key-str)) ?\s) " " 164 | str (and (not completion) "\n"))) 165 | (when completion 166 | (add-text-properties 167 | 0 (length str) 168 | `(consult--candidate ,(car reg) ,@props) 169 | str)) 170 | str)) 171 | 172 | (defun consult-register--alist (&optional noerror pred) 173 | "Return register list, sorted and filtered with PRED. 174 | Raise an error if the list is empty and NOERROR is nil." 175 | (or (sort (cl-loop for reg in register-alist 176 | ;; Sometimes, registers are made without a `cdr' or with 177 | ;; invalid markers. Such registers don't do anything, and 178 | ;; can be ignored. 179 | if (when-let ((val (cdr reg))) 180 | (and (or (not (markerp val)) (marker-buffer val)) 181 | (or (not pred) (funcall pred val)))) 182 | collect reg) 183 | #'car-less-than-car) 184 | (and (not noerror) (user-error "All registers are empty")))) 185 | 186 | (defun consult-register--candidates (&optional pred) 187 | "Return formatted completion candidates, filtered with PRED." 188 | (mapcar (lambda (reg) (consult-register-format reg 'completion)) 189 | (consult-register--alist nil pred))) 190 | 191 | ;;;###autoload 192 | (defun consult-register (&optional arg) 193 | "Load register and either jump to location or insert the stored text. 194 | 195 | This command is useful to search the register contents. For quick access 196 | to registers it is still recommended to use the register functions 197 | `consult-register-load' and `consult-register-store' or the built-in 198 | built-in register access functions. The command supports narrowing, see 199 | `consult-register--narrow'. Marker positions are previewed. See 200 | `jump-to-register' and `insert-register' for the meaning of prefix ARG." 201 | (interactive "P") 202 | (consult-register-load 203 | (consult--read 204 | (consult-register--candidates) 205 | :prompt "Register: " 206 | :category 'multi-category 207 | :state 208 | (let ((preview (consult--jump-preview))) 209 | (lambda (action cand) 210 | ;; Preview only markers 211 | (funcall preview action 212 | (when-let (reg (get-register cand)) 213 | (and (markerp reg) reg))))) 214 | :group (consult--type-group consult-register--narrow) 215 | :narrow (consult--type-narrow consult-register--narrow) 216 | :sort nil 217 | :require-match t 218 | :history t ;; disable history 219 | :lookup #'consult--lookup-candidate) 220 | arg)) 221 | 222 | ;;;###autoload 223 | (defun consult-register-load (reg &optional arg) 224 | "Do what I mean with a REG. 225 | 226 | For a window configuration, restore it. For a number or text, insert it. 227 | For a location, jump to it. See `jump-to-register' and `insert-register' 228 | for the meaning of prefix ARG." 229 | (interactive 230 | (list 231 | (and (consult-register--alist) 232 | (register-read-with-preview "Load register: ")) 233 | current-prefix-arg)) 234 | (condition-case err 235 | (jump-to-register reg arg) 236 | (user-error 237 | (unless (string-search "access aborted" (error-message-string err)) 238 | (insert-register reg (not arg)))))) 239 | 240 | (defun consult-register--action (action-list) 241 | "Read register key and execute action from ACTION-LIST. 242 | 243 | This function is derived from `register-read-with-preview'." 244 | (let* ((buffer "*Register Preview*") 245 | (prefix (car action-list)) 246 | (action-list (cdr action-list)) 247 | (action (car (nth 0 action-list))) 248 | (preview 249 | (lambda () 250 | (unless (get-buffer-window buffer) 251 | (register-preview buffer 'show-empty) 252 | (when-let (win (get-buffer-window buffer)) 253 | (with-selected-window win 254 | (let ((inhibit-read-only t)) 255 | (goto-char (point-max)) 256 | (insert 257 | (propertize (concat prefix ": ") 'face 'consult-help) 258 | (mapconcat 259 | (lambda (x) 260 | (concat (propertize (format "M-%c" (car x)) 'face 'consult-key) 261 | " " (propertize (cadr x) 'face 'consult-help))) 262 | action-list " ")) 263 | (fit-window-to-buffer))))))) 264 | (timer (when (numberp register-preview-delay) 265 | (run-at-time register-preview-delay nil preview))) 266 | (help-chars (seq-remove #'get-register (cons help-char help-event-list))) 267 | key reg) 268 | (unwind-protect 269 | (while (not reg) 270 | (while (memq (setq key 271 | (read-key (propertize (caddr (assq action action-list)) 272 | 'face 'minibuffer-prompt))) 273 | help-chars) 274 | (funcall preview)) 275 | (setq key (if (and (eql key ?\e) (characterp last-input-event)) 276 | ;; in terminal Emacs M-letter is read as two keys, ESC and the letter, 277 | ;; use what would have been read in graphical Emacs 278 | (logior #x8000000 last-input-event) 279 | last-input-event)) 280 | (cond 281 | ((or (eq ?\C-g key) 282 | (eq 'escape key) 283 | (eq ?\C-\[ key)) 284 | (keyboard-quit)) 285 | ((and (numberp key) (assq (logxor #x8000000 key) action-list)) 286 | (setq action (logxor #x8000000 key))) 287 | ((characterp key) 288 | (setq reg key)) 289 | (t (user-error "Non-character input")))) 290 | (when (timerp timer) 291 | (cancel-timer timer)) 292 | (let ((w (get-buffer-window buffer))) 293 | (when (window-live-p w) 294 | (delete-window w))) 295 | (when (get-buffer buffer) 296 | (kill-buffer buffer))) 297 | (when reg 298 | (funcall (cadddr (assq action action-list)) reg)))) 299 | 300 | ;;;###autoload 301 | (defun consult-register-store (arg) 302 | "Store register dependent on current context, showing an action menu. 303 | 304 | With an active region, store/append/prepend the contents, optionally 305 | deleting the region when a prefix ARG is given. With a numeric prefix 306 | ARG, store or add the number. Otherwise store point, frameset, window or 307 | kmacro." 308 | (interactive "P") 309 | (consult-register--action 310 | (cond 311 | ((use-region-p) 312 | (let ((beg (region-beginning)) 313 | (end (region-end))) 314 | `("Region" 315 | (?c "copy" "Copy region to register: " ,(lambda (r) (copy-to-register r beg end arg t))) 316 | (?a "append" "Append region to register: " ,(lambda (r) (append-to-register r beg end arg))) 317 | (?p "prepend" "Prepend region to register: " ,(lambda (r) (prepend-to-register r beg end arg)))))) 318 | ((numberp arg) 319 | `(,(format "Number %s" arg) 320 | (?s "store" ,(format "Store %s in register: " arg) ,(lambda (r) (number-to-register arg r))) 321 | (?a "add" ,(format "Add %s to register: " arg) ,(lambda (r) (increment-register arg r))))) 322 | (t 323 | `("Store" 324 | (?p "point" "Point to register: " ,#'point-to-register) 325 | ,@(when-let ((file (or buffer-file-name default-directory))) 326 | `((?f "file" "File to register: " ,(lambda (r) (set-register r `(file . ,file)))))) 327 | (?b "buffer" "Buffer to register: " ,(lambda (r) (set-register r `(buffer . ,(buffer-name))))) 328 | (?t "frameset" "Frameset to register: " ,#'frameset-to-register) 329 | (?w "window" "Window to register: " ,#'window-configuration-to-register) 330 | ,@(and last-kbd-macro `((?k "kmacro" "Kmacro to register: " ,#'kmacro-to-register)))))))) 331 | 332 | (provide 'consult-register) 333 | ;;; consult-register.el ends here 334 | -------------------------------------------------------------------------------- /consult-xref.el: -------------------------------------------------------------------------------- 1 | ;;; consult-xref.el --- Xref integration for Consult -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2021-2025 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of GNU Emacs. 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Provides Xref integration for Consult. This is an extra package, to 23 | ;; allow lazy loading of xref.el. The `consult-xref' function is 24 | ;; autoloaded. 25 | 26 | ;;; Code: 27 | 28 | (require 'consult) 29 | (require 'xref) 30 | (eval-when-compile (require 'subr-x)) 31 | 32 | (defvar consult-xref--history nil) 33 | 34 | (defvar consult-xref--fetcher nil 35 | "The current xref fetcher. 36 | The fetch is stored globally such that it can be accessed by 37 | Embark for `embark-export'.") 38 | 39 | (defvar consult-xref--preview 40 | '(xref-buffer-location xref-file-location xref-etags-location) 41 | "Only the xref types listed here are previewed.") 42 | 43 | (defun consult-xref--candidates () 44 | "Return xref candidate list." 45 | (let ((root (consult--project-root))) 46 | (mapcar (lambda (xref) 47 | (let* ((loc (xref-item-location xref)) 48 | (group (xref-location-group loc)) 49 | (group (if root (string-remove-prefix root group) group)) 50 | (cand (consult--format-file-line-match 51 | group 52 | (or (xref-location-line loc) 0) 53 | (xref-item-summary xref)))) 54 | (add-text-properties 55 | 0 1 `(consult-xref ,xref consult--prefix-group ,group) cand) 56 | cand)) 57 | (funcall consult-xref--fetcher)))) 58 | 59 | (defun consult-xref--preview (display) 60 | "Xref preview with DISPLAY function." 61 | (let ((open (consult--temporary-files)) 62 | (preview (consult--jump-preview))) 63 | (lambda (action cand) 64 | (unless cand 65 | (funcall open)) 66 | (let ((consult--buffer-display display)) 67 | (funcall preview action 68 | (when-let ((loc (and cand (eq action 'preview) 69 | (xref-item-location cand))) 70 | (type (type-of loc)) 71 | ;; Only preview xrefs listed in consult-xref--preview 72 | ((memq type consult-xref--preview))) 73 | (pcase type 74 | ((or 'xref-file-location 'xref-etags-location) 75 | (consult--marker-from-line-column 76 | (funcall open 77 | ;; xref-location-group returns the file name 78 | (let ((xref-file-name-display 'abs)) 79 | (xref-location-group loc))) 80 | (xref-location-line loc) 81 | (if (eq type 'xref-file-location) 82 | (xref-file-location-column loc) 83 | 0))) 84 | (_ (xref-location-marker loc))))))))) 85 | 86 | ;;;###autoload 87 | (defun consult-xref (fetcher &optional alist) 88 | "Show xrefs with preview in the minibuffer. 89 | 90 | This function can be used for `xref-show-xrefs-function'. 91 | See `xref-show-xrefs-function' for the description of the 92 | FETCHER and ALIST arguments." 93 | (let* ((consult-xref--fetcher fetcher) 94 | (candidates (consult-xref--candidates)) 95 | (display (alist-get 'display-action alist)) 96 | (this-command #'consult-xref)) 97 | (unless candidates 98 | (user-error "No xref locations")) 99 | (xref-pop-to-location 100 | (if (cdr candidates) 101 | (consult--read 102 | candidates 103 | :prompt "Go to xref: " 104 | :history 'consult-xref--history 105 | :require-match t 106 | :sort nil 107 | :category 'consult-xref 108 | :group #'consult--prefix-group 109 | :state 110 | ;; do not preview other frame 111 | (when-let (fun (pcase-exhaustive display 112 | ('frame nil) 113 | ('window #'switch-to-buffer-other-window) 114 | ('nil #'switch-to-buffer))) 115 | (consult-xref--preview fun)) 116 | :lookup (apply-partially #'consult--lookup-prop 'consult-xref)) 117 | (get-text-property 0 'consult-xref (car candidates))) 118 | display))) 119 | 120 | (provide 'consult-xref) 121 | ;;; consult-xref.el ends here 122 | --------------------------------------------------------------------------------