[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/consult 93bdcd2cda 1/4: docs: add 'Hacking' section
From: |
ELPA Syncer |
Subject: |
[elpa] externals/consult 93bdcd2cda 1/4: docs: add 'Hacking' section |
Date: |
Fri, 15 Nov 2024 00:57:50 -0500 (EST) |
branch: externals/consult
commit 93bdcd2cdadad3422cee59f681c8247a07175f90
Author: Sean Allred <allred.sean@gmail.com>
Commit: Daniel Mendler <mail@daniel-mendler.de>
docs: add 'Hacking' section
While many examples exist in the current codebase, the basic process
for using a new asynchronous completion source can get lost in the
sophistication of examples like `consult-rg` and friends.
Introduce a 'Hacking' section to the README that describes the bare
minimum required to do this -- including live preview.
---
README.org | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/README.org b/README.org
index 49ac998ee7..af43229490 100644
--- a/README.org
+++ b/README.org
@@ -1112,6 +1112,90 @@ Please provide the necessary important information with
your bug report:
When evaluating Consult-related code snippets you should enable
[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical
binding]].
Consult often relies on lambdas and lexical closures.
+* Hacking
+** Creating a new asynchronous completion source
+
+If you have a completion source that's both dynamic and expensive to generate,
+=completing-read= may not be the best choice. Instead, =consult--read= serves
as a
+thin wrapper around =completing-read= that provides this functionality.
+
+For example, consider the following script that splits its input on space:
+
+#+begin_src sh
+ #!/usr/bin/env bash
+
+ # simulate work
+ sleep .1
+
+ # generate completion candidates
+ printf "%s\n" "$*" | tr " " "\n" | sort
+#+end_src
+
+Let's assume this script is callable as =testibus hello world=.
+
+To have Consult use it as a completion source, use =consult--async-command=:
+
+#+begin_src emacs-lisp
+ (consult--read
+ (consult--async-command (lambda (input) (list "testibus" (s-trim input))))
+ :prompt "run testibus: ")
+#+end_src
+
+If your completion source is generated by Lisp instead, use
+=consult--dynamic-collection=:
+
+#+begin_src emacs-lisp
+ (consult--read
+ (consult--dynamic-collection
+ (lambda (input)
+ (sit-for 0.1)
+ (thread-first
+ (string-trim input)
+ (split-string nil t)
+ (sort #'string<)))))
+ :prompt "run testibus: ")
+#+end_src
+
+*** ...with live preview
+
+Implementing live preview is a little more involved and requires the definition
+of a =STATE= function as defined by =consult--with-preview=.
+
+The =STATE= function receives the candidate and some action to perform (e.g.,
+='preview=). In its simplest form supporting live preview, it looks something
like
+this:
+
+#+begin_src emacs-lisp
+ (defun testibus--state ()
+ (lambda (action cand)
+ (pcase action
+ ('preview
+ (with-current-buffer-window " *testibus*" 'action nil
+ (erase-buffer)
+ (insert (format "input: %s\n" cand)))))))
+#+end_src
+
+See =consult--with-preview= for the lifecycle of =ACTION=.
+
+Once defined, we can use this =STATE= function in =consult--read=:
+
+#+begin_src emacs-lisp
+ (consult--read
+ (consult--dynamic-collection
+ (lambda (input)
+ (sit-for 0.1)
+ (thread-first
+ (string-trim input)
+ (split-string nil t)
+ (sort #'string<))))
+ :prompt "run testibus: "
+ :state (testibus--state))
+#+end_src
+
+Note that depending on how expensive the ='preview= logic is, you may wish to
take
+advantage of the built-in threading support or use an external package such as
+[[https://github.com/jwiegley/emacs-async][emacs-async]].
+
* Contributions
:properties:
:description: Feature requests and pull requests
@@ -1171,3 +1255,7 @@ Smith]], [[https://github.com/manuel-uberti/][Manuel
Uberti]], [[https://github.
:end:
#+html: -->
+
+# Local Variables:
+# fill-column: 80
+# End: