-
-
Notifications
You must be signed in to change notification settings - Fork 389
Developing
The best way to learn how to create a custom Helm command is to read the source code and look at examples. A good place to start is the helm-info.el file, which is fairly short and straightforward.
That being said, we’ll try to go over some basic ideas in this (far from comprehensive) Wiki.
The helm
function creates a Helm buffer with candidates to select and/or take action on. The list of candidates is provided by one or more sources.
An example usage of helm
is below:
(defun my-first-helm-command ()
(interactive)
(helm :sources 'my-source
:buffer "*helm my command*"))
helm
must be called with several keywords arguments.
Mandatory.
Expects a source of the form:
- Single source (alist)
- Symbol naming the source
- List of sources (alist or symbol)
Examples are below:
;; Alist
sources '((name . "test") (candidates . (a b c d)))
;; List of alists
:sources '(((name . "test") (candidates . (a b c d)))
((name . "test2") (candidates . (e f g h))))
;; Symbol
:sources 'helm-source-1
;; List of symbols
:sources '(helm-source-1 helm-source-2 helm-source-3)
Optional but important.
The value for the :buffer
keyword helps the helm-resume
command retrieve the Helm session.
The name of the buffer should be prefixed with helm
(e.g. *helm Info*
). This is not mandatory, but it is good practice. It will, among other things, allow Helm to automatically hide the buffer.
Even if you can still create source with alists, helm provide convenient basic classes to build sources, and allow you creating your own classes inheriting from these basics classes.
Here are the basic classes for creating a Helm source:
-
helm-source-sync
, which puts candidates in a list. -
helm-source-in-buffer
, which puts candidates in a buffer. -
helm-source-async
, which gets candidates asynchronously using the output of a process. -
helm-source-dummy
, which use thehelm-pattern
as candidate. -
helm-source-in-file
, which gets candidates from the lines of a named file usinghelm-source-in-buffer
.
For consistency, prefix your source names with helm-source-
(e.g. helm-source-info-emacs
).
For convenience, helm
provide macros prefixed by helm-build-
to
build your sources quickly, see examples below.
All the different slots are documented in docstring of each classes.
(helm-build-sync-source "test"
:candidates '(a b c d e))
(helm :sources (helm-build-sync-source "test"
:candidates '(a b c d e))
:buffer "*helm sync source*")
(helm-build-in-buffer-source "test1"
:data '(a b c d e))
(helm :sources (helm-build-in-buffer-source "test1"
:data '(a b c d e))
:buffer "*helm buffer source*")
(helm :sources (helm-build-async-source "test2"
:candidates-process
(lambda ()
(start-process "echo" nil "echo" "a\nb\nc\nd\ne")))
:buffer "*helm async source*")
To give a specific help to your Helm source, create a variable helm-<my-source>-help-string
and bind it in your source with the helm-message
slot. It will then will appear when you use C-h m
or C-c ?
.
(defclass my-helm-class (helm-source-sync)
((candidates :initform '("foo" "bar" "baz"))))
(helm :sources (helm-make-source "test" 'my-helm-class)
:buffer "*helm test*")
Is the same as creating your source with:
(helm :sources (helm-build-sync-source "test"
:candidates '("foo" "bar" "baz"))
:buffer "*helm test*")
Here an example from a helm user that store a list of favorite files in a file ~/.fav
to retrieve them quickly:
(defclass helm-test-fav (helm-source-in-file helm-type-file)
((candidates-file :initform "~/.fav")))
(helm :sources (helm-make-source "test" 'helm-test-fav)
:buffer "*helm test*")
Once your class is created, you have to use helm-make-source
to build your
source.
You will find several examples in the helm-types.el file.
The main thing to remember is to create an empty source and fill it
using two defmethod’s, one empty which should be a primary method and
one which is a before method, use for this the slots :primary
and
:before
of defmethod
.
This allow you overhiding the different slots of the inheriting type
class in your new class.
Class names are currently a mess. Need to come up with a better convention.