Code Snippets for Clojure LSP
Clojure LSP snippets are an editor agnostic approach to expanding common code forms from snippet names, saving typing and acting as a guide to the syntax of a Clojure form. Practicalli also uses snippets for rich comments, documentation and highlighting logical sections of code in a namespace.
Clojure LSP snippets are defined using the EDN syntax and have the same tab stop syntax as Yasnippets and other snippet tools.
Clojure LSP snippets are covered in Practiclli Spacemacs, including a large number of examples of custom snippets. Install practicalli/clojure-lsp-config for additions to the built-in snippets.
Clojure-lsp snippets
Clojure LSP includes snippets as part of the completion feature, so when typing the name of a snippet it will appear in a completion popup. In the same way that happens for Clojure functions and other symbols.
- Built-in clojure-lsp snippets
- practicalli/clojure-lsp-config with additional snippets
Writing Custom snippets
Creating custom snippets by adding :additional-snippets
key to the Clojure LSP configuration, either .lsp/config.edn
in the root of the project or in the global config ($XDG_CONFIG_HOME/clojure-lsp/config.edn
or $HOME/.lsp/config.edn
)
The :additional-snippets
key is associated with a vector or hash-maps, [{}{},,,]
with each hash-map defining a snippet using the keys:
:name
- name of the snippet, typed into the editor for completion
:detail
- a meaningful description of the snippet
:snippet
- the definition of the snippet, with tab stops and current-form syntax
The :snippet
can be any text, ideally with syntax that is correct for the particular language
practicalli/clojure-lsp-config defines additional snippets, including clojure.core functions, documentation, rich comments and Clojure CLI dependencies.
Snippets and Tab Stops
Tab stops are a way to customise the generated snippet text, so unique values for that snippet can be added.
Include $
with a number, e.g. $1
,$2
,$3
, to include tab stops in the snippet. Once the snippet code has been generated, TAB
key jumps through the tab stops in sequence, allowing customisation of a generic snippet.
${1:placeholder-text}
adds placeholder text on a first tab stop, providing a guide to the type of value should be entered. The default text is replaces when typing in the tab stop.
Using a tab stop number multiple times will concurrently add text to all matching tab stops
$0
marks the final position of the cursor, after which TAB
has no more positions in the snippet to jump to.
{:name "deps-git-url"
:detail "Git URL dependency"
:snippet
"${1:domain/library-name}
{:git/url \"https://github.com/$1\"
:git/sha \"${2:git-sha-value}\"}$0"}
Snippet current-form
Snippets using $current-form
will pull in the next Clojure form when expanding the snippet.
{:additional-snippets
[{:name "wrap-let-sexp"
:detail "Wrap sexpr in let form"
:snippet "(let [${1:name} $current-form] $0)"}]}
Expanding wrap-let-sexp
before the form (* 2 21)
will create the form (let [life (* 2 21)])
(when life
is typed into the first tab stop placeholder).
Note that a snippet containing $current-form will only be active when typing directly in front of an existing Clojure expression. At the top level LSP will act like the Snippet does not exist.
Clojure code driven snippet - built-in snippets only
The built-in defn
snippet uses Clojure code to help generate the snippet.
%s
is a substitution point within a snippet, used by the standard Clojure format
command. The value substituted is either defn ^:private
or defn-
, depending on the value returned from the if
expression.
:use-metadata-for-privacy?
is a key from the Clojure LSP configuration, set to true
or false
{:label "defn-"
:detail "Create private function"
:insert-text (format "(defn%s ${1:name} [$2]\n ${0:body})"
(if (:use-metadata-for-privacy? settings)
" ^:private"
"-"))}
The syntax for built-in snippets is slightly different that the :additional-syntax
form. The internal form uses :label
for :name
and :insert-text
for :snippet
.
Clojure code only works for built-in snippets and not
:additional-snippets
. Clojure LSP is compiled by Graal to a native binary, including the built-in snippets. To include Clojure code in a snippet then consider submitting a pull request to the Clojure LSP project to add a built-in snippet.
Clojure LSP snippets are defined in clojure-lsp.feature.completion-snippet
namespace.
Summary
Clojure LSP can define quite rich text expansions and built-in snippets can go further using Clojure code to expand the text.
Clojure LSP snippets and Yasnippets are covered in more detail in Practiclli Spacemacs, including a large number of examples of custom snippets
practicalli/clojure-lsp-config repository contains numerous additional snippets (that hopefully will be added to the built-in snippets).