summaryrefslogtreecommitdiff
path: root/emacs.d
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-07-18 12:25:58 +0300
committerLars Wirzenius <liw@liw.fi>2021-07-18 12:25:58 +0300
commitad392a22b55ef278797753b82f10e4cd50a8febb (patch)
treefe4b393b30b355434a67899fa5772d6563fab82f /emacs.d
parentba6730976e5ec75116cfb8eab85209f03e288336 (diff)
downloadliw-dot-files-ad392a22b55ef278797753b82f10e4cd50a8febb.tar.gz
emacs: add elpa files
Sponsored-by: author
Diffstat (limited to 'emacs.d')
-rw-r--r--emacs.d/.lsp-session-v11
-rw-r--r--emacs.d/elpa/archives/gnu/archive-contents.signed1
-rw-r--r--emacs.d/elpa/dash-20210708.2009/dash-autoloads.el74
-rw-r--r--emacs.d/elpa/dash-20210708.2009/dash-pkg.el12
-rw-r--r--emacs.d/elpa/dash-20210708.2009/dash.el3533
-rw-r--r--emacs.d/elpa/dash-20210708.2009/dash.info4738
-rw-r--r--emacs.d/elpa/dash-20210708.2009/dir18
-rw-r--r--emacs.d/elpa/ht-20210119.741/ht-autoloads.el22
-rw-r--r--emacs.d/elpa/ht-20210119.741/ht-pkg.el2
-rw-r--r--emacs.d/elpa/ht-20210119.741/ht.el337
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-actionscript.el134
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-ada.el74
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-angular.el82
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-bash.el90
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-beancount.el71
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-clangd.el304
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-clojure.el308
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-cmake.el43
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-completion.el779
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-crystal.el48
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-csharp.el365
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-css.el254
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-d.el37
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-dhall.el43
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-diagnostics.el369
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-dired.el178
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-dockerfile.el66
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-elixir.el190
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-elm.el137
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-erlang.el67
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-eslint.el355
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-fortran.el61
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-fsharp.el305
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-gdscript.el61
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-go.el338
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-groovy.el66
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-hack.el54
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-haxe.el226
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-headerline.el473
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-html.el198
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-icons.el96
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-ido.el142
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-iedit.el101
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-javascript.el334
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-json.el131
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-kotlin.el121
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-lens.el425
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-lua.el678
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-markdown.el105
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-autoloads.el745
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-pkg.el18
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode.el8656
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-modeline.el354
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-nim.el45
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-nix.el48
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-ocaml.el84
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-perl.el117
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-php.el433
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-prolog.el55
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-protocol.el752
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-purescript.el72
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-pwsh.el360
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-pyls.el504
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-pylsp.el434
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-r.el49
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-racket.el77
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-rf.el147
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-rust.el1100
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-semantic-tokens.el758
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-solargraph.el166
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-sorbet.el59
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-sqls.el190
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-steep.el73
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-svelte.el307
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-terraform.el68
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-tex.el68
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-v.el50
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-vala.el51
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-verilog.el186
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-vetur.el869
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-vhdl.el121
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-vimscript.el75
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-xml.el245
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-yaml.el242
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp-zig.el50
-rw-r--r--emacs.d/elpa/lsp-mode-20210716.2233/lsp.el8
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-autoloads.el80
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.el1195
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.html43
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-flycheck.el171
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-imenu.el412
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-peek.el754
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-pkg.el15
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-sideline.el768
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-util.el71
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/lsp-ui.el177
-rw-r--r--emacs.d/elpa/lsp-ui-20210718.445/resources/lightbulb.pngbin0 -> 2058 bytes
-rw-r--r--emacs.d/elpa/lv-20200507.1518/lv-autoloads.el22
-rw-r--r--emacs.d/elpa/lv-20200507.1518/lv-pkg.el2
-rw-r--r--emacs.d/elpa/lv-20200507.1518/lv.el150
-rw-r--r--emacs.d/elpa/project-0.6.0.signed1
-rw-r--r--emacs.d/elpa/project-0.6.0/project-autoloads.el234
-rw-r--r--emacs.d/elpa/project-0.6.0/project-pkg.el2
-rw-r--r--emacs.d/elpa/project-0.6.0/project.el1401
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-autoloads.el382
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-babel.el288
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-cargo.el530
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-compile.el540
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-doc.el385
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-flycheck.el201
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-interaction.el425
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-lsp.el170
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-pkg.el20
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-playpen.el61
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-popup.el241
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-racer.el515
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-rustfix.el33
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic-rustfmt.el301
-rw-r--r--emacs.d/elpa/rustic-20210609.1900/rustic.el1253
-rw-r--r--emacs.d/elpa/spinner-1.7.4.signed1
-rw-r--r--emacs.d/elpa/spinner-1.7.4/README.org76
-rw-r--r--emacs.d/elpa/spinner-1.7.4/all-spinners.gifbin0 -> 18314 bytes
-rw-r--r--emacs.d/elpa/spinner-1.7.4/some-spinners.gifbin0 -> 1932043 bytes
-rw-r--r--emacs.d/elpa/spinner-1.7.4/spinner-autoloads.el77
-rw-r--r--emacs.d/elpa/spinner-1.7.4/spinner-pkg.el2
-rw-r--r--emacs.d/elpa/spinner-1.7.4/spinner.el340
-rw-r--r--emacs.d/elpa/xref-1.1.0.signed1
-rw-r--r--emacs.d/elpa/xref-1.1.0/xref-autoloads.el110
-rw-r--r--emacs.d/elpa/xref-1.1.0/xref-pkg.el2
-rw-r--r--emacs.d/elpa/xref-1.1.0/xref.el1744
-rw-r--r--emacs.d/elpa/xterm-color-20200605.2017/xterm-color-autoloads.el82
-rw-r--r--emacs.d/elpa/xterm-color-20200605.2017/xterm-color-pkg.el2
-rw-r--r--emacs.d/elpa/xterm-color-20200605.2017/xterm-color.el938
133 files changed, 48501 insertions, 0 deletions
diff --git a/emacs.d/.lsp-session-v1 b/emacs.d/.lsp-session-v1
new file mode 100644
index 0000000..4b1b5fd
--- /dev/null
+++ b/emacs.d/.lsp-session-v1
@@ -0,0 +1 @@
+#s(lsp-session ("/home/liw/pers/vmadm/git") nil #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ()) #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ()) #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ())) \ No newline at end of file
diff --git a/emacs.d/elpa/archives/gnu/archive-contents.signed b/emacs.d/elpa/archives/gnu/archive-contents.signed
new file mode 100644
index 0000000..7e93e80
--- /dev/null
+++ b/emacs.d/elpa/archives/gnu/archive-contents.signed
@@ -0,0 +1 @@
+Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2021-07-16T00:05:02+0300 using RSA \ No newline at end of file
diff --git a/emacs.d/elpa/dash-20210708.2009/dash-autoloads.el b/emacs.d/elpa/dash-20210708.2009/dash-autoloads.el
new file mode 100644
index 0000000..3a96693
--- /dev/null
+++ b/emacs.d/elpa/dash-20210708.2009/dash-autoloads.el
@@ -0,0 +1,74 @@
+;;; dash-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "dash" "dash.el" (0 0 0 0))
+;;; Generated autoloads from dash.el
+
+(autoload 'dash-fontify-mode "dash" "\
+Toggle fontification of Dash special variables.
+
+If called interactively, enable Dash-Fontify mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is `toggle'; disable the mode otherwise.
+
+Dash-Fontify mode is a buffer-local minor mode intended for Emacs
+Lisp buffers. Enabling it causes the special variables bound in
+anaphoric Dash macros to be fontified. These anaphoras include
+`it', `it-index', `acc', and `other'. In older Emacs versions
+which do not dynamically detect macros, Dash-Fontify mode
+additionally fontifies Dash macro calls.
+
+See also `dash-fontify-mode-lighter' and
+`global-dash-fontify-mode'.
+
+\(fn &optional ARG)" t nil)
+
+(put 'global-dash-fontify-mode 'globalized-minor-mode t)
+
+(defvar global-dash-fontify-mode nil "\
+Non-nil if Global Dash-Fontify mode is enabled.
+See the `global-dash-fontify-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `global-dash-fontify-mode'.")
+
+(custom-autoload 'global-dash-fontify-mode "dash" nil)
+
+(autoload 'global-dash-fontify-mode "dash" "\
+Toggle Dash-Fontify mode in all buffers.
+With prefix ARG, enable Global Dash-Fontify mode if ARG is positive;
+otherwise, disable it. If called from Lisp, enable the mode if
+ARG is omitted or nil.
+
+Dash-Fontify mode is enabled in all buffers where
+`dash--turn-on-fontify-mode' would do it.
+See `dash-fontify-mode' for more information on Dash-Fontify mode.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'dash-register-info-lookup "dash" "\
+Register the Dash Info manual with `info-lookup-symbol'.
+This allows Dash symbols to be looked up with \\[info-lookup-symbol]." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-juxt" "-keep" "-l" "-m" "-no" "-o" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; dash-autoloads.el ends here
diff --git a/emacs.d/elpa/dash-20210708.2009/dash-pkg.el b/emacs.d/elpa/dash-20210708.2009/dash-pkg.el
new file mode 100644
index 0000000..97c683b
--- /dev/null
+++ b/emacs.d/elpa/dash-20210708.2009/dash-pkg.el
@@ -0,0 +1,12 @@
+(define-package "dash" "20210708.2009" "A modern list library for Emacs"
+ '((emacs "24"))
+ :commit "2675596b9ac1c4b9d47b93e227f06f8ec6755ec6" :authors
+ '(("Magnar Sveen" . "magnars@gmail.com"))
+ :maintainer
+ '("Magnar Sveen" . "magnars@gmail.com")
+ :keywords
+ '("extensions" "lisp")
+ :url "https://github.com/magnars/dash.el")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/emacs.d/elpa/dash-20210708.2009/dash.el b/emacs.d/elpa/dash-20210708.2009/dash.el
new file mode 100644
index 0000000..4e56da4
--- /dev/null
+++ b/emacs.d/elpa/dash-20210708.2009/dash.el
@@ -0,0 +1,3533 @@
+;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
+
+;; Author: Magnar Sveen <magnars@gmail.com>
+;; Version: 2.19.0
+;; Package-Requires: ((emacs "24"))
+;; Keywords: extensions, lisp
+;; Homepage: https://github.com/magnars/dash.el
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A modern list API for Emacs.
+;;
+;; See its overview at https://github.com/magnars/dash.el#functions.
+
+;;; Code:
+
+;; TODO: `gv' was introduced in Emacs 24.3, so remove this and all
+;; calls to `defsetf' when support for earlier versions is dropped.
+(eval-when-compile
+ (unless (fboundp 'gv-define-setter)
+ (require 'cl)))
+
+(defgroup dash ()
+ "Customize group for Dash, a modern list library."
+ :group 'extensions
+ :group 'lisp
+ :prefix "dash-")
+
+(defmacro !cons (car cdr)
+ "Destructive: Set CDR to the cons of CAR and CDR."
+ (declare (debug (form symbolp)))
+ `(setq ,cdr (cons ,car ,cdr)))
+
+(defmacro !cdr (list)
+ "Destructive: Set LIST to the cdr of LIST."
+ (declare (debug (symbolp)))
+ `(setq ,list (cdr ,list)))
+
+(defmacro --each (list &rest body)
+ "Evaluate BODY for each element of LIST and return nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating BODY.
+This is the anaphoric counterpart to `-each'."
+ (declare (debug (form body)) (indent 1))
+ (let ((l (make-symbol "list"))
+ (i (make-symbol "i")))
+ `(let ((,l ,list)
+ (,i 0)
+ it it-index)
+ (ignore it it-index)
+ (while ,l
+ (setq it (pop ,l) it-index ,i ,i (1+ ,i))
+ ,@body))))
+
+(defun -each (list fn)
+ "Call FN on each element of LIST.
+Return nil; this function is intended for side effects.
+
+Its anaphoric counterpart is `--each'.
+
+For access to the current element's index in LIST, see
+`-each-indexed'."
+ (declare (indent 1))
+ (ignore (mapc fn list)))
+
+(defalias '--each-indexed '--each)
+
+(defun -each-indexed (list fn)
+ "Call FN on each index and element of LIST.
+For each ITEM at INDEX in LIST, call (funcall FN INDEX ITEM).
+Return nil; this function is intended for side effects.
+
+See also: `-map-indexed'."
+ (declare (indent 1))
+ (--each list (funcall fn it-index it)))
+
+(defmacro --each-while (list pred &rest body)
+ "Evaluate BODY for each item in LIST, while PRED evaluates to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating PRED or BODY. Once
+an element is reached for which PRED evaluates to nil, no further
+BODY is evaluated. The return value is always nil.
+This is the anaphoric counterpart to `-each-while'."
+ (declare (debug (form form body)) (indent 2))
+ (let ((l (make-symbol "list"))
+ (i (make-symbol "i"))
+ (elt (make-symbol "elt")))
+ `(let ((,l ,list)
+ (,i 0)
+ ,elt it it-index)
+ (ignore it it-index)
+ (while (and ,l (setq ,elt (pop ,l) it ,elt it-index ,i) ,pred)
+ (setq it ,elt it-index ,i ,i (1+ ,i))
+ ,@body))))
+
+(defun -each-while (list pred fn)
+ "Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil.
+Once an ITEM is reached for which PRED returns nil, FN is no
+longer called. Return nil; this function is intended for side
+effects.
+
+Its anaphoric counterpart is `--each-while'."
+ (declare (indent 2))
+ (--each-while list (funcall pred it) (funcall fn it)))
+
+(defmacro --each-r (list &rest body)
+ "Evaluate BODY for each element of LIST in reversed order.
+Each element of LIST in turn, starting at its end, is bound to
+`it' and its index within LIST to `it-index' before evaluating
+BODY. The return value is always nil.
+This is the anaphoric counterpart to `-each-r'."
+ (declare (debug (form body)) (indent 1))
+ (let ((v (make-symbol "vector"))
+ (i (make-symbol "i")))
+ ;; Implementation note: building a vector is considerably faster
+ ;; than building a reversed list (vector takes less memory, so
+ ;; there is less GC), plus `length' comes naturally. In-place
+ ;; `nreverse' would be faster still, but BODY would be able to see
+ ;; that, even if the modification was undone before we return.
+ `(let* ((,v (vconcat ,list))
+ (,i (length ,v))
+ it it-index)
+ (ignore it it-index)
+ (while (> ,i 0)
+ (setq ,i (1- ,i) it-index ,i it (aref ,v ,i))
+ ,@body))))
+
+(defun -each-r (list fn)
+ "Call FN on each element of LIST in reversed order.
+Return nil; this function is intended for side effects.
+
+Its anaphoric counterpart is `--each-r'."
+ (--each-r list (funcall fn it)))
+
+(defmacro --each-r-while (list pred &rest body)
+ "Eval BODY for each item in reversed LIST, while PRED evals to non-nil.
+Each element of LIST in turn, starting at its end, is bound to
+`it' and its index within LIST to `it-index' before evaluating
+PRED or BODY. Once an element is reached for which PRED
+evaluates to nil, no further BODY is evaluated. The return value
+is always nil.
+This is the anaphoric counterpart to `-each-r-while'."
+ (declare (debug (form form body)) (indent 2))
+ (let ((v (make-symbol "vector"))
+ (i (make-symbol "i"))
+ (elt (make-symbol "elt")))
+ `(let* ((,v (vconcat ,list))
+ (,i (length ,v))
+ ,elt it it-index)
+ (ignore it it-index)
+ (while (when (> ,i 0)
+ (setq ,i (1- ,i) it-index ,i)
+ (setq ,elt (aref ,v ,i) it ,elt)
+ ,pred)
+ (setq it-index ,i it ,elt)
+ ,@body))))
+
+(defun -each-r-while (list pred fn)
+ "Call FN on each ITEM in reversed LIST, while (PRED ITEM) is non-nil.
+Once an ITEM is reached for which PRED returns nil, FN is no
+longer called. Return nil; this function is intended for side
+effects.
+
+Its anaphoric counterpart is `--each-r-while'."
+ (--each-r-while list (funcall pred it) (funcall fn it)))
+
+(defmacro --dotimes (num &rest body)
+ "Evaluate BODY NUM times, presumably for side effects.
+BODY is evaluated with the local variable `it' temporarily bound
+to successive integers running from 0, inclusive, to NUM,
+exclusive. BODY is not evaluated if NUM is less than 1.
+This is the anaphoric counterpart to `-dotimes'."
+ (declare (debug (form body)) (indent 1))
+ (let ((n (make-symbol "num"))
+ (i (make-symbol "i")))
+ `(let ((,n ,num)
+ (,i 0)
+ it)
+ (ignore it)
+ (while (< ,i ,n)
+ (setq it ,i ,i (1+ ,i))
+ ,@body))))
+
+(defun -dotimes (num fn)
+ "Call FN NUM times, presumably for side effects.
+FN is called with a single argument on successive integers
+running from 0, inclusive, to NUM, exclusive. FN is not called
+if NUM is less than 1.
+
+This function's anaphoric counterpart is `--dotimes'."
+ (declare (indent 1))
+ (--dotimes num (funcall fn it)))
+
+(defun -map (fn list)
+ "Apply FN to each item in LIST and return the list of results.
+
+This function's anaphoric counterpart is `--map'."
+ (mapcar fn list))
+
+(defmacro --map (form list)
+ "Eval FORM for each item in LIST and return the list of results.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM.
+This is the anaphoric counterpart to `-map'."
+ (declare (debug (def-form form)))
+ `(mapcar (lambda (it) (ignore it) ,form) ,list))
+
+(defmacro --reduce-from (form init list)
+ "Accumulate a value by evaluating FORM across LIST.
+This macro is like `--each' (which see), but it additionally
+provides an accumulator variable `acc' which it successively
+binds to the result of evaluating FORM for the current LIST
+element before processing the next element. For the first
+element, `acc' is initialized with the result of evaluating INIT.
+The return value is the resulting value of `acc'. If LIST is
+empty, FORM is not evaluated, and the return value is the result
+of INIT.
+This is the anaphoric counterpart to `-reduce-from'."
+ (declare (debug (form form form)))
+ `(let ((acc ,init))
+ (--each ,list (setq acc ,form))
+ acc))
+
+(defun -reduce-from (fn init list)
+ "Reduce the function FN across LIST, starting with INIT.
+Return the result of applying FN to INIT and the first element of
+LIST, then applying FN to that result and the second element,
+etc. If LIST is empty, return INIT without calling FN.
+
+This function's anaphoric counterpart is `--reduce-from'.
+
+For other folds, see also `-reduce' and `-reduce-r'."
+ (--reduce-from (funcall fn acc it) init list))
+
+(defmacro --reduce (form list)
+ "Accumulate a value by evaluating FORM across LIST.
+This macro is like `--reduce-from' (which see), except the first
+element of LIST is taken as INIT. Thus if LIST contains a single
+item, it is returned without evaluating FORM. If LIST is empty,
+FORM is evaluated with `it' and `acc' bound to nil.
+This is the anaphoric counterpart to `-reduce'."
+ (declare (debug (form form)))
+ (let ((lv (make-symbol "list-value")))
+ `(let ((,lv ,list))
+ (if ,lv
+ (--reduce-from ,form (car ,lv) (cdr ,lv))
+ ;; Explicit nil binding pacifies lexical "variable left uninitialized"
+ ;; warning. See issue #377 and upstream https://bugs.gnu.org/47080.
+ (let ((acc nil) (it nil))
+ (ignore acc it)
+ ,form)))))
+
+(defun -reduce (fn list)
+ "Reduce the function FN across LIST.
+Return the result of applying FN to the first two elements of
+LIST, then applying FN to that result and the third element, etc.
+If LIST contains a single element, return it without calling FN.
+If LIST is empty, return the result of calling FN with no
+arguments.
+
+This function's anaphoric counterpart is `--reduce'.
+
+For other folds, see also `-reduce-from' and `-reduce-r'."
+ (if list
+ (-reduce-from fn (car list) (cdr list))
+ (funcall fn)))
+
+(defmacro --reduce-r-from (form init list)
+ "Accumulate a value by evaluating FORM across LIST in reverse.
+This macro is like `--reduce-from', except it starts from the end
+of LIST.
+This is the anaphoric counterpart to `-reduce-r-from'."
+ (declare (debug (form form form)))
+ `(let ((acc ,init))
+ (--each-r ,list (setq acc ,form))
+ acc))
+
+(defun -reduce-r-from (fn init list)
+ "Reduce the function FN across LIST in reverse, starting with INIT.
+Return the result of applying FN to the last element of LIST and
+INIT, then applying FN to the second-to-last element and the
+previous result of FN, etc. That is, the first argument of FN is
+the current element, and its second argument the accumulated
+value. If LIST is empty, return INIT without calling FN.
+
+This function is like `-reduce-from' but the operation associates
+from the right rather than left. In other words, it starts from
+the end of LIST and flips the arguments to FN. Conceptually, it
+is like replacing the conses in LIST with applications of FN, and
+its last link with INIT, and evaluating the resulting expression.
+
+This function's anaphoric counterpart is `--reduce-r-from'.
+
+For other folds, see also `-reduce-r' and `-reduce'."
+ (--reduce-r-from (funcall fn it acc) init list))
+
+(defmacro --reduce-r (form list)
+ "Accumulate a value by evaluating FORM across LIST in reverse order.
+This macro is like `--reduce', except it starts from the end of
+LIST.
+This is the anaphoric counterpart to `-reduce-r'."
+ (declare (debug (form form)))
+ `(--reduce ,form (reverse ,list)))
+
+(defun -reduce-r (fn list)
+ "Reduce the function FN across LIST in reverse.
+Return the result of applying FN to the last two elements of
+LIST, then applying FN to the third-to-last element and the
+previous result of FN, etc. That is, the first argument of FN is
+the current element, and its second argument the accumulated
+value. If LIST contains a single element, return it without
+calling FN. If LIST is empty, return the result of calling FN
+with no arguments.
+
+This function is like `-reduce' but the operation associates from
+the right rather than left. In other words, it starts from the
+end of LIST and flips the arguments to FN. Conceptually, it is
+like replacing the conses in LIST with applications of FN,
+ignoring its last link, and evaluating the resulting expression.
+
+This function's anaphoric counterpart is `--reduce-r'.
+
+For other folds, see also `-reduce-r-from' and `-reduce'."
+ (if list
+ (--reduce-r (funcall fn it acc) list)
+ (funcall fn)))
+
+(defmacro --reductions-from (form init list)
+ "Return a list of FORM's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-from' (which see) is called with the same
+arguments.
+This is the anaphoric counterpart to `-reductions-from'."
+ (declare (debug (form form form)))
+ `(nreverse
+ (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+ (list ,init)
+ ,list)))
+
+(defun -reductions-from (fn init list)
+ "Return a list of FN's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-from' (which see) is called with the same
+arguments.
+
+This function's anaphoric counterpart is `--reductions-from'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+ (--reductions-from (funcall fn acc it) init list))
+
+(defmacro --reductions (form list)
+ "Return a list of FORM's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce' (which see) is called with the same arguments.
+This is the anaphoric counterpart to `-reductions'."
+ (declare (debug (form form)))
+ (let ((lv (make-symbol "list-value")))
+ `(let ((,lv ,list))
+ (if ,lv
+ (--reductions-from ,form (car ,lv) (cdr ,lv))
+ (let (acc it)
+ (ignore acc it)
+ (list ,form))))))
+
+(defun -reductions (fn list)
+ "Return a list of FN's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce' (which see) is called with the same arguments.
+
+This function's anaphoric counterpart is `--reductions'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+ (if list
+ (--reductions-from (funcall fn acc it) (car list) (cdr list))
+ (list (funcall fn))))
+
+(defmacro --reductions-r-from (form init list)
+ "Return a list of FORM's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-r-from' (which see) is called with the same
+arguments.
+This is the anaphoric counterpart to `-reductions-r-from'."
+ (declare (debug (form form form)))
+ `(--reduce-r-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+ (list ,init)
+ ,list))
+
+(defun -reductions-r-from (fn init list)
+ "Return a list of FN's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-r-from' (which see) is called with the same
+arguments.
+
+This function's anaphoric counterpart is `--reductions-r-from'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+ (--reductions-r-from (funcall fn it acc) init list))
+
+(defmacro --reductions-r (form list)
+ "Return a list of FORM's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-re' (which see) is called with the same arguments.
+This is the anaphoric counterpart to `-reductions-r'."
+ (declare (debug (form list)))
+ (let ((lv (make-symbol "list-value")))
+ `(let ((,lv (reverse ,list)))
+ (if ,lv
+ (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+ (list (car ,lv))
+ (cdr ,lv))
+ ;; Explicit nil binding pacifies lexical "variable left uninitialized"
+ ;; warning. See issue #377 and upstream https://bugs.gnu.org/47080.
+ (let ((acc nil) (it nil))
+ (ignore acc it)
+ (list ,form))))))
+
+(defun -reductions-r (fn list)
+ "Return a list of FN's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-r' (which see) is called with the same arguments.
+
+This function's anaphoric counterpart is `--reductions-r'.
+
+For other folds, see also `-reductions-r-from' and
+`-reductions'."
+ (if list
+ (--reductions-r (funcall fn it acc) list)
+ (list (funcall fn))))
+
+(defmacro --filter (form list)
+ "Return a new list of the items in LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-filter'.
+For the opposite operation, see also `--remove'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list (when ,form (push it ,r)))
+ (nreverse ,r))))
+
+(defun -filter (pred list)
+ "Return a new list of the items in LIST for which PRED returns non-nil.
+
+Alias: `-select'.
+
+This function's anaphoric counterpart is `--filter'.
+
+For similar operations, see also `-keep' and `-remove'."
+ (--filter (funcall pred it) list))
+
+(defalias '-select '-filter)
+(defalias '--select '--filter)
+
+(defmacro --remove (form list)
+ "Return a new list of the items in LIST for which FORM evals to nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-remove'.
+For the opposite operation, see also `--filter'."
+ (declare (debug (form form)))
+ `(--filter (not ,form) ,list))
+
+(defun -remove (pred list)
+ "Return a new list of the items in LIST for which PRED returns nil.
+
+Alias: `-reject'.
+
+This function's anaphoric counterpart is `--remove'.
+
+For similar operations, see also `-keep' and `-filter'."
+ (--remove (funcall pred it) list))
+
+(defalias '-reject '-remove)
+(defalias '--reject '--remove)
+
+(defmacro --remove-first (form list)
+ "Remove the first item from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM. This is a
+non-destructive operation, but only the front of LIST leading up
+to the removed item is a copy; the rest is LIST's original tail.
+If no item is removed, then the result is a complete copy.
+This is the anaphoric counterpart to `-remove-first'."
+ (declare (debug (form form)))
+ (let ((front (make-symbol "front"))
+ (tail (make-symbol "tail")))
+ `(let ((,tail ,list) ,front)
+ (--each-while ,tail (not ,form)
+ (push (pop ,tail) ,front))
+ (if ,tail
+ (nconc (nreverse ,front) (cdr ,tail))
+ (nreverse ,front)))))
+
+(defun -remove-first (pred list)
+ "Remove the first item from LIST for which PRED returns non-nil.
+This is a non-destructive operation, but only the front of LIST
+leading up to the removed item is a copy; the rest is LIST's
+original tail. If no item is removed, then the result is a
+complete copy.
+
+Alias: `-reject-first'.
+
+This function's anaphoric counterpart is `--remove-first'.
+
+See also `-map-first', `-remove-item', and `-remove-last'."
+ (--remove-first (funcall pred it) list))
+
+(defalias '-reject-first '-remove-first)
+(defalias '--reject-first '--remove-first)
+
+(defmacro --remove-last (form list)
+ "Remove the last item from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM. The result is a copy of LIST regardless of whether an
+element is removed.
+This is the anaphoric counterpart to `-remove-last'."
+ (declare (debug (form form)))
+ `(nreverse (--remove-first ,form (reverse ,list))))
+
+(defun -remove-last (pred list)
+ "Remove the last item from LIST for which PRED returns non-nil.
+The result is a copy of LIST regardless of whether an element is
+removed.
+
+Alias: `-reject-last'.
+
+This function's anaphoric counterpart is `--remove-last'.
+
+See also `-map-last', `-remove-item', and `-remove-first'."
+ (--remove-last (funcall pred it) list))
+
+(defalias '-reject-last '-remove-last)
+(defalias '--reject-last '--remove-last)
+
+(defalias '-remove-item #'remove
+ "Return a copy of LIST with all occurrences of ITEM removed.
+The comparison is done with `equal'.
+\n(fn ITEM LIST)")
+
+(defmacro --keep (form list)
+ "Eval FORM for each item in LIST and return the non-nil results.
+Like `--filter', but returns the non-nil results of FORM instead
+of the corresponding elements of LIST. Each element of LIST in
+turn is bound to `it' and its index within LIST to `it-index'
+before evaluating FORM.
+This is the anaphoric counterpart to `-keep'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result"))
+ (m (make-symbol "mapped")))
+ `(let (,r)
+ (--each ,list (let ((,m ,form)) (when ,m (push ,m ,r))))
+ (nreverse ,r))))
+
+(defun -keep (fn list)
+ "Return a new list of the non-nil results of applying FN to each item in LIST.
+Like `-filter', but returns the non-nil results of FN instead of
+the corresponding elements of LIST.
+
+Its anaphoric counterpart is `--keep'."
+ (--keep (funcall fn it) list))
+
+(defun -non-nil (list)
+ "Return a copy of LIST with all nil items removed."
+ (declare (pure t) (side-effect-free t))
+ (--filter it list))
+
+(defmacro --map-indexed (form list)
+ "Eval FORM for each item in LIST and return the list of results.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM. This is like
+`--map', but additionally makes `it-index' available to FORM.
+
+This is the anaphoric counterpart to `-map-indexed'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list
+ (push ,form ,r))
+ (nreverse ,r))))
+
+(defun -map-indexed (fn list)
+ "Apply FN to each index and item in LIST and return the list of results.
+This is like `-map', but FN takes two arguments: the index of the
+current element within LIST, and the element itself.
+
+This function's anaphoric counterpart is `--map-indexed'.
+
+For a side-effecting variant, see also `-each-indexed'."
+ (--map-indexed (funcall fn it-index it) list))
+
+(defmacro --map-when (pred rep list)
+ "Anaphoric form of `-map-when'."
+ (declare (debug (form form form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list (!cons (if ,pred ,rep it) ,r))
+ (nreverse ,r))))
+
+(defun -map-when (pred rep list)
+ "Return a new list where the elements in LIST that do not match the PRED function
+are unchanged, and where the elements in LIST that do match the PRED function are mapped
+through the REP function.
+
+Alias: `-replace-where'
+
+See also: `-update-at'"
+ (--map-when (funcall pred it) (funcall rep it) list))
+
+(defalias '-replace-where '-map-when)
+(defalias '--replace-where '--map-when)
+
+(defun -map-first (pred rep list)
+ "Replace first item in LIST satisfying PRED with result of REP called on this item.
+
+See also: `-map-when', `-replace-first'"
+ (let (front)
+ (while (and list (not (funcall pred (car list))))
+ (push (car list) front)
+ (!cdr list))
+ (if list
+ (-concat (nreverse front) (cons (funcall rep (car list)) (cdr list)))
+ (nreverse front))))
+
+(defmacro --map-first (pred rep list)
+ "Anaphoric form of `-map-first'."
+ (declare (debug (def-form def-form form)))
+ `(-map-first (lambda (it) ,pred) (lambda (it) (ignore it) ,rep) ,list))
+
+(defun -map-last (pred rep list)
+ "Replace last item in LIST satisfying PRED with result of REP called on this item.
+
+See also: `-map-when', `-replace-last'"
+ (nreverse (-map-first pred rep (reverse list))))
+
+(defmacro --map-last (pred rep list)
+ "Anaphoric form of `-map-last'."
+ (declare (debug (def-form def-form form)))
+ `(-map-last (lambda (it) ,pred) (lambda (it) (ignore it) ,rep) ,list))
+
+(defun -replace (old new list)
+ "Replace all OLD items in LIST with NEW.
+
+Elements are compared using `equal'.
+
+See also: `-replace-at'"
+ (declare (pure t) (side-effect-free t))
+ (--map-when (equal it old) new list))
+
+(defun -replace-first (old new list)
+ "Replace the first occurrence of OLD with NEW in LIST.
+
+Elements are compared using `equal'.
+
+See also: `-map-first'"
+ (declare (pure t) (side-effect-free t))
+ (--map-first (equal old it) new list))
+
+(defun -replace-last (old new list)
+ "Replace the last occurrence of OLD with NEW in LIST.
+
+Elements are compared using `equal'.
+
+See also: `-map-last'"
+ (declare (pure t) (side-effect-free t))
+ (--map-last (equal old it) new list))
+
+(defmacro --mapcat (form list)
+ "Anaphoric form of `-mapcat'."
+ (declare (debug (form form)))
+ `(apply 'append (--map ,form ,list)))
+
+(defun -mapcat (fn list)
+ "Return the concatenation of the result of mapping FN over LIST.
+Thus function FN should return a list."
+ (--mapcat (funcall fn it) list))
+
+(defmacro --iterate (form init n)
+ "Anaphoric version of `-iterate'."
+ (declare (debug (form form form)))
+ (let ((res (make-symbol "result"))
+ (len (make-symbol "n")))
+ `(let ((,len ,n))
+ (when (> ,len 0)
+ (let* ((it ,init)
+ (,res (list it)))
+ (dotimes (_ (1- ,len))
+ (push (setq it ,form) ,res))
+ (nreverse ,res))))))
+
+(defun -iterate (fun init n)
+ "Return a list of iterated applications of FUN to INIT.
+
+This means a list of the form:
+
+ (INIT (FUN INIT) (FUN (FUN INIT)) ...)
+
+N is the length of the returned list."
+ (--iterate (funcall fun it) init n))
+
+(defun -flatten (l)
+ "Take a nested list L and return its contents as a single, flat list.
+
+Note that because `nil' represents a list of zero elements (an
+empty list), any mention of nil in L will disappear after
+flattening. If you need to preserve nils, consider `-flatten-n'
+or map them to some unique symbol and then map them back.
+
+Conses of two atoms are considered \"terminals\", that is, they
+aren't flattened further.
+
+See also: `-flatten-n'"
+ (declare (pure t) (side-effect-free t))
+ (if (and (listp l) (listp (cdr l)))
+ (-mapcat '-flatten l)
+ (list l)))
+
+(defun -flatten-n (num list)
+ "Flatten NUM levels of a nested LIST.
+
+See also: `-flatten'"
+ (declare (pure t) (side-effect-free t))
+ (dotimes (_ num)
+ (setq list (apply #'append (mapcar #'-list list))))
+ list)
+
+(defun -concat (&rest lists)
+ "Return a new list with the concatenation of the elements in the supplied LISTS."
+ (declare (pure t) (side-effect-free t))
+ (apply 'append lists))
+
+(defalias '-copy 'copy-sequence
+ "Create a shallow copy of LIST.
+
+\(fn LIST)")
+
+(defun -splice (pred fun list)
+ "Splice lists generated by FUN in place of elements matching PRED in LIST.
+
+FUN takes the element matching PRED as input.
+
+This function can be used as replacement for `,@' in case you
+need to splice several lists at marked positions (for example
+with keywords).
+
+See also: `-splice-list', `-insert-at'"
+ (let (r)
+ (--each list
+ (if (funcall pred it)
+ (let ((new (funcall fun it)))
+ (--each new (!cons it r)))
+ (!cons it r)))
+ (nreverse r)))
+
+(defmacro --splice (pred form list)
+ "Anaphoric form of `-splice'."
+ (declare (debug (def-form def-form form)))
+ `(-splice (lambda (it) ,pred) (lambda (it) ,form) ,list))
+
+(defun -splice-list (pred new-list list)
+ "Splice NEW-LIST in place of elements matching PRED in LIST.
+
+See also: `-splice', `-insert-at'"
+ (-splice pred (lambda (_) new-list) list))
+
+(defmacro --splice-list (pred new-list list)
+ "Anaphoric form of `-splice-list'."
+ (declare (debug (def-form form form)))
+ `(-splice-list (lambda (it) ,pred) ,new-list ,list))
+
+(defun -cons* (&rest args)
+ "Make a new list from the elements of ARGS.
+The last 2 elements of ARGS are used as the final cons of the
+result, so if the final element of ARGS is not a list, the result
+is a dotted list. With no ARGS, return nil."
+ (declare (pure t) (side-effect-free t))
+ (let* ((len (length args))
+ (tail (nthcdr (- len 2) args))
+ (last (cdr tail)))
+ (if (null last)
+ (car args)
+ (setcdr tail (car last))
+ args)))
+
+(defun -snoc (list elem &rest elements)
+ "Append ELEM to the end of the list.
+
+This is like `cons', but operates on the end of list.
+
+If ELEMENTS is non nil, append these to the list as well."
+ (-concat list (list elem) elements))
+
+(defmacro --first (form list)
+ "Return the first item in LIST for which FORM evals to non-nil.
+Return nil if no such element is found.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-first'."
+ (declare (debug (form form)))
+ (let ((n (make-symbol "needle")))
+ `(let (,n)
+ (--each-while ,list (or (not ,form)
+ (ignore (setq ,n it))))
+ ,n)))
+
+(defun -first (pred list)
+ "Return the first item in LIST for which PRED returns non-nil.
+Return nil if no such element is found.
+To get the first item in the list no questions asked, use `car'.
+
+Alias: `-find'.
+
+This function's anaphoric counterpart is `--first'."
+ (--first (funcall pred it) list))
+
+(defalias '-find '-first)
+(defalias '--find '--first)
+
+(defmacro --some (form list)
+ "Return non-nil if FORM evals to non-nil for at least one item in LIST.
+If so, return the first such result of FORM.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-some'."
+ (declare (debug (form form)))
+ (let ((n (make-symbol "needle")))
+ `(let (,n)
+ (--each-while ,list (not (setq ,n ,form)))
+ ,n)))
+
+(defun -some (pred list)
+ "Return (PRED x) for the first LIST item where (PRED x) is non-nil, else nil.
+
+Alias: `-any'.
+
+This function's anaphoric counterpart is `--some'."
+ (--some (funcall pred it) list))
+
+(defalias '-any '-some)
+(defalias '--any '--some)
+
+(defmacro --every (form list)
+ "Return non-nil if FORM evals to non-nil for all items in LIST.
+If so, return the last such result of FORM. Otherwise, once an
+item is reached for which FORM yields nil, return nil without
+evaluating FORM for any further LIST elements.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+
+This macro is like `--every-p', but on success returns the last
+non-nil result of FORM instead of just t.
+
+This is the anaphoric counterpart to `-every'."
+ (declare (debug (form form)))
+ (let ((a (make-symbol "all")))
+ `(let ((,a t))
+ (--each-while ,list (setq ,a ,form))
+ ,a)))
+
+(defun -every (pred list)
+ "Return non-nil if PRED returns non-nil for all items in LIST.
+If so, return the last such result of PRED. Otherwise, once an
+item is reached for which PRED returns nil, return nil without
+calling PRED on any further LIST elements.
+
+This function is like `-every-p', but on success returns the last
+non-nil result of PRED instead of just t.
+
+This function's anaphoric counterpart is `--every'."
+ (--every (funcall pred it) list))
+
+(defmacro --last (form list)
+ "Anaphoric form of `-last'."
+ (declare (debug (form form)))
+ (let ((n (make-symbol "needle")))
+ `(let (,n)
+ (--each ,list
+ (when ,form (setq ,n it)))
+ ,n)))
+
+(defun -last (pred list)
+ "Return the last x in LIST where (PRED x) is non-nil, else nil."
+ (--last (funcall pred it) list))
+
+(defalias '-first-item 'car
+ "Return the first item of LIST, or nil on an empty list.
+
+See also: `-second-item', `-last-item'.
+
+\(fn LIST)")
+
+;; Ensure that calls to `-first-item' are compiled to a single opcode,
+;; just like `car'.
+(put '-first-item 'byte-opcode 'byte-car)
+(put '-first-item 'byte-compile 'byte-compile-one-arg)
+
+(defalias '-second-item 'cadr
+ "Return the second item of LIST, or nil if LIST is too short.
+
+See also: `-third-item'.
+
+\(fn LIST)")
+
+(defalias '-third-item
+ (if (fboundp 'caddr)
+ #'caddr
+ (lambda (list) (car (cddr list))))
+ "Return the third item of LIST, or nil if LIST is too short.
+
+See also: `-fourth-item'.
+
+\(fn LIST)")
+
+(defun -fourth-item (list)
+ "Return the fourth item of LIST, or nil if LIST is too short.
+
+See also: `-fifth-item'."
+ (declare (pure t) (side-effect-free t))
+ (car (cdr (cdr (cdr list)))))
+
+(defun -fifth-item (list)
+ "Return the fifth item of LIST, or nil if LIST is too short.
+
+See also: `-last-item'."
+ (declare (pure t) (side-effect-free t))
+ (car (cdr (cdr (cdr (cdr list))))))
+
+(defun -last-item (list)
+ "Return the last item of LIST, or nil on an empty list."
+ (declare (pure t) (side-effect-free t))
+ (car (last list)))
+
+;; Use `with-no-warnings' to suppress unbound `-last-item' or
+;; undefined `gv--defsetter' warnings arising from both
+;; `gv-define-setter' and `defsetf' in certain Emacs versions.
+(with-no-warnings
+ (if (fboundp 'gv-define-setter)
+ (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val))
+ (defsetf -last-item (x) (val) `(setcar (last ,x) ,val))))
+
+(defun -butlast (list)
+ "Return a list of all items in list except for the last."
+ ;; no alias as we don't want magic optional argument
+ (declare (pure t) (side-effect-free t))
+ (butlast list))
+
+(defmacro --count (pred list)
+ "Anaphoric form of `-count'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result")))
+ `(let ((,r 0))
+ (--each ,list (when ,pred (setq ,r (1+ ,r))))
+ ,r)))
+
+(defun -count (pred list)
+ "Counts the number of items in LIST where (PRED item) is non-nil."
+ (--count (funcall pred it) list))
+
+(defun ---truthy? (obj)
+ "Return OBJ as a boolean value (t or nil)."
+ (declare (pure t) (side-effect-free t))
+ (and obj t))
+
+(defmacro --any? (form list)
+ "Anaphoric form of `-any?'."
+ (declare (debug (form form)))
+ `(and (--some ,form ,list) t))
+
+(defun -any? (pred list)
+ "Return t if (PRED x) is non-nil for any x in LIST, else nil.
+
+Alias: `-any-p', `-some?', `-some-p'"
+ (--any? (funcall pred it) list))
+
+(defalias '-some? '-any?)
+(defalias '--some? '--any?)
+(defalias '-any-p '-any?)
+(defalias '--any-p '--any?)
+(defalias '-some-p '-any?)
+(defalias '--some-p '--any?)
+
+(defmacro --all? (form list)
+ "Return t if FORM evals to non-nil for all items in LIST.
+Otherwise, once an item is reached for which FORM yields nil,
+return nil without evaluating FORM for any further LIST elements.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+
+The similar macro `--every' is more widely useful, since it
+returns the last non-nil result of FORM instead of just t on
+success.
+
+Alias: `--all-p', `--every-p', `--every?'.
+
+This is the anaphoric counterpart to `-all?'."
+ (declare (debug (form form)))
+ `(and (--every ,form ,list) t))
+
+(defun -all? (pred list)
+ "Return t if (PRED X) is non-nil for all X in LIST, else nil.
+In the latter case, stop after the first X for which (PRED X) is
+nil, without calling PRED on any subsequent elements of LIST.
+
+The similar function `-every' is more widely useful, since it
+returns the last non-nil result of PRED instead of just t on
+success.
+
+Alias: `-all-p', `-every-p', `-every?'.
+
+This function's anaphoric counterpart is `--all?'."
+ (--all? (funcall pred it) list))
+
+(defalias '-every? '-all?)
+(defalias '--every? '--all?)
+(defalias '-all-p '-all?)
+(defalias '--all-p '--all?)
+(defalias '-every-p '-all?)
+(defalias '--every-p '--all?)
+
+(defmacro --none? (form list)
+ "Anaphoric form of `-none?'."
+ (declare (debug (form form)))
+ `(--all? (not ,form) ,list))
+
+(defun -none? (pred list)
+ "Return t if (PRED x) is nil for all x in LIST, else nil.
+
+Alias: `-none-p'"
+ (--none? (funcall pred it) list))
+
+(defalias '-none-p '-none?)
+(defalias '--none-p '--none?)
+
+(defmacro --only-some? (form list)
+ "Anaphoric form of `-only-some?'."
+ (declare (debug (form form)))
+ (let ((y (make-symbol "yes"))
+ (n (make-symbol "no")))
+ `(let (,y ,n)
+ (--each-while ,list (not (and ,y ,n))
+ (if ,form (setq ,y t) (setq ,n t)))
+ (---truthy? (and ,y ,n)))))
+
+(defun -only-some? (pred list)
+ "Return `t` if at least one item of LIST matches PRED and at least one item of LIST does not match PRED.
+Return `nil` both if all items match the predicate or if none of the items match the predicate.
+
+Alias: `-only-some-p'"
+ (--only-some? (funcall pred it) list))
+
+(defalias '-only-some-p '-only-some?)
+(defalias '--only-some-p '--only-some?)
+
+(defun -slice (list from &optional to step)
+ "Return copy of LIST, starting from index FROM to index TO.
+
+FROM or TO may be negative. These values are then interpreted
+modulo the length of the list.
+
+If STEP is a number, only each STEPth item in the resulting
+section is returned. Defaults to 1."
+ (declare (pure t) (side-effect-free t))
+ (let ((length (length list))
+ (new-list nil))
+ ;; to defaults to the end of the list
+ (setq to (or to length))
+ (setq step (or step 1))
+ ;; handle negative indices
+ (when (< from 0)
+ (setq from (mod from length)))
+ (when (< to 0)
+ (setq to (mod to length)))
+
+ ;; iterate through the list, keeping the elements we want
+ (--each-while list (< it-index to)
+ (when (and (>= it-index from)
+ (= (mod (- from it-index) step) 0))
+ (push it new-list)))
+ (nreverse new-list)))
+
+(defmacro --take-while (form list)
+ "Take successive items from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM. Return a new
+list of the successive elements from the start of LIST for which
+FORM evaluates to non-nil.
+This is the anaphoric counterpart to `-take-while'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each-while ,list ,form (push it ,r))
+ (nreverse ,r))))
+
+(defun -take-while (pred list)
+ "Take successive items from LIST for which PRED returns non-nil.
+PRED is a function of one argument. Return a new list of the
+successive elements from the start of LIST for which PRED returns
+non-nil.
+
+This function's anaphoric counterpart is `--take-while'.
+
+For another variant, see also `-drop-while'."
+ (--take-while (funcall pred it) list))
+
+(defmacro --drop-while (form list)
+ "Drop successive items from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM. Return the
+tail (not a copy) of LIST starting from its first element for
+which FORM evaluates to nil.
+This is the anaphoric counterpart to `-drop-while'."
+ (declare (debug (form form)))
+ (let ((l (make-symbol "list")))
+ `(let ((,l ,list))
+ (--each-while ,l ,form (pop ,l))
+ ,l)))
+
+(defun -drop-while (pred list)
+ "Drop successive items from LIST for which PRED returns non-nil.
+PRED is a function of one argument. Return the tail (not a copy)
+of LIST starting from its first element for which PRED returns
+nil.
+
+This function's anaphoric counterpart is `--drop-while'.
+
+For another variant, see also `-take-while'."
+ (--drop-while (funcall pred it) list))
+
+(defun -take (n list)
+ "Return a copy of the first N items in LIST.
+Return a copy of LIST if it contains N items or fewer.
+Return nil if N is zero or less.
+
+See also: `-take-last'."
+ (declare (pure t) (side-effect-free t))
+ (--take-while (< it-index n) list))
+
+(defun -take-last (n list)
+ "Return a copy of the last N items of LIST in order.
+Return a copy of LIST if it contains N items or fewer.
+Return nil if N is zero or less.
+
+See also: `-take'."
+ (declare (pure t) (side-effect-free t))
+ (copy-sequence (last list n)))
+
+(defalias '-drop #'nthcdr
+ "Return the tail (not a copy) of LIST without the first N items.
+Return nil if LIST contains N items or fewer.
+Return LIST if N is zero or less.
+
+For another variant, see also `-drop-last'.
+\n(fn N LIST)")
+
+(defun -drop-last (n list)
+ "Return a copy of LIST without its last N items.
+Return a copy of LIST if N is zero or less.
+Return nil if LIST contains N items or fewer.
+
+See also: `-drop'."
+ (declare (pure t) (side-effect-free t))
+ (nbutlast (copy-sequence list) n))
+
+(defun -split-at (n list)
+ "Split LIST into two sublists after the Nth element.
+The result is a list of two elements (TAKE DROP) where TAKE is a
+new list of the first N elements of LIST, and DROP is the
+remaining elements of LIST (not a copy). TAKE and DROP are like
+the results of `-take' and `-drop', respectively, but the split
+is done in a single list traversal."
+ (declare (pure t) (side-effect-free t))
+ (let (result)
+ (--each-while list (< it-index n)
+ (push (pop list) result))
+ (list (nreverse result) list)))
+
+(defun -rotate (n list)
+ "Rotate LIST N places to the right (left if N is negative).
+The time complexity is O(n)."
+ (declare (pure t) (side-effect-free t))
+ (cond ((null list) ())
+ ((zerop n) (copy-sequence list))
+ ((let* ((len (length list))
+ (n-mod-len (mod n len))
+ (new-tail-len (- len n-mod-len)))
+ (append (nthcdr new-tail-len list) (-take new-tail-len list))))))
+
+(defun -insert-at (n x list)
+ "Return a list with X inserted into LIST at position N.
+
+See also: `-splice', `-splice-list'"
+ (declare (pure t) (side-effect-free t))
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons x (cadr split-list)))))
+
+(defun -replace-at (n x list)
+ "Return a list with element at Nth position in LIST replaced with X.
+
+See also: `-replace'"
+ (declare (pure t) (side-effect-free t))
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons x (cdr (cadr split-list))))))
+
+(defun -update-at (n func list)
+ "Return a list with element at Nth position in LIST replaced with `(func (nth n list))`.
+
+See also: `-map-when'"
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons (funcall func (car (cadr split-list))) (cdr (cadr split-list))))))
+
+(defmacro --update-at (n form list)
+ "Anaphoric version of `-update-at'."
+ (declare (debug (form def-form form)))
+ `(-update-at ,n (lambda (it) ,form) ,list))
+
+(defun -remove-at (n list)
+ "Return a list with element at Nth position in LIST removed.
+
+See also: `-remove-at-indices', `-remove'"
+ (declare (pure t) (side-effect-free t))
+ (-remove-at-indices (list n) list))
+
+(defun -remove-at-indices (indices list)
+ "Return a list whose elements are elements from LIST without
+elements selected as `(nth i list)` for all i
+from INDICES.
+
+See also: `-remove-at', `-remove'"
+ (declare (pure t) (side-effect-free t))
+ (let* ((indices (-sort '< indices))
+ (diffs (cons (car indices) (-map '1- (-zip-with '- (cdr indices) indices))))
+ r)
+ (--each diffs
+ (let ((split (-split-at it list)))
+ (!cons (car split) r)
+ (setq list (cdr (cadr split)))))
+ (!cons list r)
+ (apply '-concat (nreverse r))))
+
+(defmacro --split-with (pred list)
+ "Anaphoric form of `-split-with'."
+ (declare (debug (form form)))
+ (let ((l (make-symbol "list"))
+ (r (make-symbol "result"))
+ (c (make-symbol "continue")))
+ `(let ((,l ,list)
+ (,r nil)
+ (,c t))
+ (while (and ,l ,c)
+ (let ((it (car ,l)))
+ (if (not ,pred)
+ (setq ,c nil)
+ (!cons it ,r)
+ (!cdr ,l))))
+ (list (nreverse ,r) ,l))))
+
+(defun -split-with (pred list)
+ "Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), in no more than one pass through the list."
+ (--split-with (funcall pred it) list))
+
+(defmacro -split-on (item list)
+ "Split the LIST each time ITEM is found.
+
+Unlike `-partition-by', the ITEM is discarded from the results.
+Empty lists are also removed from the result.
+
+Comparison is done by `equal'.
+
+See also `-split-when'"
+ (declare (debug (def-form form)))
+ `(-split-when (lambda (it) (equal it ,item)) ,list))
+
+(defmacro --split-when (form list)
+ "Anaphoric version of `-split-when'."
+ (declare (debug (def-form form)))
+ `(-split-when (lambda (it) ,form) ,list))
+
+(defun -split-when (fn list)
+ "Split the LIST on each element where FN returns non-nil.
+
+Unlike `-partition-by', the \"matched\" element is discarded from
+the results. Empty lists are also removed from the result.
+
+This function can be thought of as a generalization of
+`split-string'."
+ (let (r s)
+ (while list
+ (if (not (funcall fn (car list)))
+ (push (car list) s)
+ (when s (push (nreverse s) r))
+ (setq s nil))
+ (!cdr list))
+ (when s (push (nreverse s) r))
+ (nreverse r)))
+
+(defmacro --separate (form list)
+ "Anaphoric form of `-separate'."
+ (declare (debug (form form)))
+ (let ((y (make-symbol "yes"))
+ (n (make-symbol "no")))
+ `(let (,y ,n)
+ (--each ,list (if ,form (!cons it ,y) (!cons it ,n)))
+ (list (nreverse ,y) (nreverse ,n)))))
+
+(defun -separate (pred list)
+ "Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one pass through the list."
+ (--separate (funcall pred it) list))
+
+(defun dash--partition-all-in-steps-reversed (n step list)
+ "Used by `-partition-all-in-steps' and `-partition-in-steps'."
+ (when (< step 1)
+ (signal 'wrong-type-argument
+ `("Step size < 1 results in juicy infinite loops" ,step)))
+ (let (result)
+ (while list
+ (push (-take n list) result)
+ (setq list (nthcdr step list)))
+ result))
+
+(defun -partition-all-in-steps (n step list)
+ "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart.
+The last groups may contain less than N items."
+ (declare (pure t) (side-effect-free t))
+ (nreverse (dash--partition-all-in-steps-reversed n step list)))
+
+(defun -partition-in-steps (n step list)
+ "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart.
+If there are not enough items to make the last group N-sized,
+those items are discarded."
+ (declare (pure t) (side-effect-free t))
+ (let ((result (dash--partition-all-in-steps-reversed n step list)))
+ (while (and result (< (length (car result)) n))
+ (!cdr result))
+ (nreverse result)))
+
+(defun -partition-all (n list)
+ "Return a new list with the items in LIST grouped into N-sized sublists.
+The last group may contain less than N items."
+ (declare (pure t) (side-effect-free t))
+ (-partition-all-in-steps n n list))
+
+(defun -partition (n list)
+ "Return a new list with the items in LIST grouped into N-sized sublists.
+If there are not enough items to make the last group N-sized,
+those items are discarded."
+ (declare (pure t) (side-effect-free t))
+ (-partition-in-steps n n list))
+
+(defmacro --partition-by (form list)
+ "Anaphoric form of `-partition-by'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result"))
+ (s (make-symbol "sublist"))
+ (v (make-symbol "value"))
+ (n (make-symbol "new-value"))
+ (l (make-symbol "list")))
+ `(let ((,l ,list))
+ (when ,l
+ (let* ((,r nil)
+ (it (car ,l))
+ (,s (list it))
+ (,v ,form)
+ (,l (cdr ,l)))
+ (while ,l
+ (let* ((it (car ,l))
+ (,n ,form))
+ (unless (equal ,v ,n)
+ (!cons (nreverse ,s) ,r)
+ (setq ,s nil)
+ (setq ,v ,n))
+ (!cons it ,s)
+ (!cdr ,l)))
+ (!cons (nreverse ,s) ,r)
+ (nreverse ,r))))))
+
+(defun -partition-by (fn list)
+ "Apply FN to each item in LIST, splitting it each time FN returns a new value."
+ (--partition-by (funcall fn it) list))
+
+(defmacro --partition-by-header (form list)
+ "Anaphoric form of `-partition-by-header'."
+ (declare (debug (form form)))
+ (let ((r (make-symbol "result"))
+ (s (make-symbol "sublist"))
+ (h (make-symbol "header-value"))
+ (b (make-symbol "seen-body?"))
+ (n (make-symbol "new-value"))
+ (l (make-symbol "list")))
+ `(let ((,l ,list))
+ (when ,l
+ (let* ((,r nil)
+ (it (car ,l))
+ (,s (list it))
+ (,h ,form)
+ (,b nil)
+ (,l (cdr ,l)))
+ (while ,l
+ (let* ((it (car ,l))
+ (,n ,form))
+ (if (equal ,h ,n)
+ (when ,b
+ (!cons (nreverse ,s) ,r)
+ (setq ,s nil)
+ (setq ,b nil))
+ (setq ,b t))
+ (!cons it ,s)
+ (!cdr ,l)))
+ (!cons (nreverse ,s) ,r)
+ (nreverse ,r))))))
+
+(defun -partition-by-header (fn list)
+ "Apply FN to the first item in LIST. That is the header
+value. Apply FN to each item in LIST, splitting it each time FN
+returns the header value, but only after seeing at least one
+other value (the body)."
+ (--partition-by-header (funcall fn it) list))
+
+(defmacro --partition-after-pred (form list)
+ "Partition LIST after each element for which FORM evaluates to non-nil.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM.
+
+This is the anaphoric counterpart to `-partition-after-pred'."
+ (let ((l (make-symbol "list"))
+ (r (make-symbol "result"))
+ (s (make-symbol "sublist")))
+ `(let ((,l ,list) ,r ,s)
+ (when ,l
+ (--each ,l
+ (push it ,s)
+ (when ,form
+ (push (nreverse ,s) ,r)
+ (setq ,s ())))
+ (when ,s
+ (push (nreverse ,s) ,r))
+ (nreverse ,r)))))
+
+(defun -partition-after-pred (pred list)
+ "Partition LIST after each element for which PRED returns non-nil.
+
+This function's anaphoric counterpart is `--partition-after-pred'."
+ (--partition-after-pred (funcall pred it) list))
+
+(defun -partition-before-pred (pred list)
+ "Partition directly before each time PRED is true on an element of LIST."
+ (nreverse (-map #'reverse
+ (-partition-after-pred pred (reverse list)))))
+
+(defun -partition-after-item (item list)
+ "Partition directly after each time ITEM appears in LIST."
+ (-partition-after-pred (lambda (ele) (equal ele item))
+ list))
+
+(defun -partition-before-item (item list)
+ "Partition directly before each time ITEM appears in LIST."
+ (-partition-before-pred (lambda (ele) (equal ele item))
+ list))
+
+(defmacro --group-by (form list)
+ "Anaphoric form of `-group-by'."
+ (declare (debug t))
+ (let ((n (make-symbol "n"))
+ (k (make-symbol "k"))
+ (grp (make-symbol "grp")))
+ `(nreverse
+ (-map
+ (lambda (,n)
+ (cons (car ,n)
+ (nreverse (cdr ,n))))
+ (--reduce-from
+ (let* ((,k (,@form))
+ (,grp (assoc ,k acc)))
+ (if ,grp
+ (setcdr ,grp (cons it (cdr ,grp)))
+ (push
+ (list ,k it)
+ acc))
+ acc)
+ nil ,list)))))
+
+(defun -group-by (fn list)
+ "Separate LIST into an alist whose keys are FN applied to the
+elements of LIST. Keys are compared by `equal'."
+ (--group-by (funcall fn it) list))
+
+(defun -interpose (sep list)
+ "Return a new list of all elements in LIST separated by SEP."
+ (declare (pure t) (side-effect-free t))
+ (let (result)
+ (when list
+ (!cons (car list) result)
+ (!cdr list))
+ (while list
+ (setq result (cons (car list) (cons sep result)))
+ (!cdr list))
+ (nreverse result)))
+
+(defun -interleave (&rest lists)
+ "Return a new list of the first item in each list, then the second etc."
+ (declare (pure t) (side-effect-free t))
+ (when lists
+ (let (result)
+ (while (-none? 'null lists)
+ (--each lists (!cons (car it) result))
+ (setq lists (-map 'cdr lists)))
+ (nreverse result))))
+
+(defmacro --zip-with (form list1 list2)
+ "Anaphoric form of `-zip-with'.
+
+The elements in list1 are bound as symbol `it', the elements in list2 as symbol `other'."
+ (declare (debug (form form form)))
+ (let ((r (make-symbol "result"))
+ (l1 (make-symbol "list1"))
+ (l2 (make-symbol "list2")))
+ `(let ((,r nil)
+ (,l1 ,list1)
+ (,l2 ,list2))
+ (while (and ,l1 ,l2)
+ (let ((it (car ,l1))
+ (other (car ,l2)))
+ (!cons ,form ,r)
+ (!cdr ,l1)
+ (!cdr ,l2)))
+ (nreverse ,r))))
+
+(defun -zip-with (fn list1 list2)
+ "Zip the two lists LIST1 and LIST2 using a function FN. This
+function is applied pairwise taking as first argument element of
+LIST1 and as second argument element of LIST2 at corresponding
+position.
+
+The anaphoric form `--zip-with' binds the elements from LIST1 as symbol `it',
+and the elements from LIST2 as symbol `other'."
+ (--zip-with (funcall fn it other) list1 list2))
+
+(defun -zip-lists (&rest lists)
+ "Zip LISTS together. Group the head of each list, followed by the
+second elements of each list, and so on. The lengths of the returned
+groupings are equal to the length of the shortest input list.
+
+The return value is always list of lists, which is a difference
+from `-zip-pair' which returns a cons-cell in case two input
+lists are provided.
+
+See also: `-zip'"
+ (declare (pure t) (side-effect-free t))
+ (when lists
+ (let (results)
+ (while (-none? 'null lists)
+ (setq results (cons (mapcar 'car lists) results))
+ (setq lists (mapcar 'cdr lists)))
+ (nreverse results))))
+
+(defun -zip (&rest lists)
+ "Zip LISTS together. Group the head of each list, followed by the
+second elements of each list, and so on. The lengths of the returned
+groupings are equal to the length of the shortest input list.
+
+If two lists are provided as arguments, return the groupings as a list
+of cons cells. Otherwise, return the groupings as a list of lists.
+
+Use `-zip-lists' if you need the return value to always be a list
+of lists.
+
+Alias: `-zip-pair'
+
+See also: `-zip-lists'"
+ (declare (pure t) (side-effect-free t))
+ (when lists
+ (let (results)
+ (while (-none? 'null lists)
+ (setq results (cons (mapcar 'car lists) results))
+ (setq lists (mapcar 'cdr lists)))
+ (setq results (nreverse results))
+ (if (= (length lists) 2)
+ ;; to support backward compatibility, return
+ ;; a cons cell if two lists were provided
+ (--map (cons (car it) (cadr it)) results)
+ results))))
+
+(defalias '-zip-pair '-zip)
+
+(defun -zip-fill (fill-value &rest lists)
+ "Zip LISTS, with FILL-VALUE padded onto the shorter lists. The
+lengths of the returned groupings are equal to the length of the
+longest input list."
+ (declare (pure t) (side-effect-free t))
+ (apply '-zip (apply '-pad (cons fill-value lists))))
+
+(defun -unzip (lists)
+ "Unzip LISTS.
+
+This works just like `-zip' but takes a list of lists instead of
+a variable number of arguments, such that
+
+ (-unzip (-zip L1 L2 L3 ...))
+
+is identity (given that the lists are the same length).
+
+Note in particular that calling this on a list of two lists will
+return a list of cons-cells such that the above identity works.
+
+See also: `-zip'"
+ (apply '-zip lists))
+
+(defun -cycle (list)
+ "Return an infinite circular copy of LIST.
+The returned list cycles through the elements of LIST and repeats
+from the beginning."
+ (declare (pure t) (side-effect-free t))
+ ;; Also works with sequences that aren't lists.
+ (let ((newlist (append list ())))
+ (nconc newlist newlist)))
+
+(defun -pad (fill-value &rest lists)
+ "Appends FILL-VALUE to the end of each list in LISTS such that they
+will all have the same length."
+ (let* ((annotations (-annotate 'length lists))
+ (n (-max (-map 'car annotations))))
+ (--map (append (cdr it) (-repeat (- n (car it)) fill-value)) annotations)))
+
+(defun -annotate (fn list)
+ "Return a list of cons cells where each cell is FN applied to each
+element of LIST paired with the unmodified element of LIST."
+ (-zip (-map fn list) list))
+
+(defmacro --annotate (form list)
+ "Anaphoric version of `-annotate'."
+ (declare (debug (def-form form)))
+ `(-annotate (lambda (it) ,form) ,list))
+
+(defun dash--table-carry (lists restore-lists &optional re)
+ "Helper for `-table' and `-table-flat'.
+
+If a list overflows, carry to the right and reset the list."
+ (while (not (or (car lists)
+ (equal lists '(nil))))
+ (setcar lists (car restore-lists))
+ (pop (cadr lists))
+ (!cdr lists)
+ (!cdr restore-lists)
+ (when re
+ (push (nreverse (car re)) (cadr re))
+ (setcar re nil)
+ (!cdr re))))
+
+(defun -table (fn &rest lists)
+ "Compute outer product of LISTS using function FN.
+
+The function FN should have the same arity as the number of
+supplied lists.
+
+The outer product is computed by applying fn to all possible
+combinations created by taking one element from each list in
+order. The dimension of the result is (length lists).
+
+See also: `-table-flat'"
+ (let ((restore-lists (copy-sequence lists))
+ (last-list (last lists))
+ (re (make-list (length lists) nil)))
+ (while (car last-list)
+ (let ((item (apply fn (-map 'car lists))))
+ (push item (car re))
+ (setcar lists (cdar lists)) ;; silence byte compiler
+ (dash--table-carry lists restore-lists re)))
+ (nreverse (car (last re)))))
+
+(defun -table-flat (fn &rest lists)
+ "Compute flat outer product of LISTS using function FN.
+
+The function FN should have the same arity as the number of
+supplied lists.
+
+The outer product is computed by applying fn to all possible
+combinations created by taking one element from each list in
+order. The results are flattened, ignoring the tensor structure
+of the result. This is equivalent to calling:
+
+ (-flatten-n (1- (length lists)) (apply \\='-table fn lists))
+
+but the implementation here is much more efficient.
+
+See also: `-flatten-n', `-table'"
+ (let ((restore-lists (copy-sequence lists))
+ (last-list (last lists))
+ re)
+ (while (car last-list)
+ (let ((item (apply fn (-map 'car lists))))
+ (push item re)
+ (setcar lists (cdar lists)) ;; silence byte compiler
+ (dash--table-carry lists restore-lists)))
+ (nreverse re)))
+
+(defun -elem-index (elem list)
+ "Return the index of the first element in the given LIST which
+is equal to the query element ELEM, or nil if there is no
+such element."
+ (declare (pure t) (side-effect-free t))
+ (car (-elem-indices elem list)))
+
+(defun -elem-indices (elem list)
+ "Return the indices of all elements in LIST equal to the query
+element ELEM, in ascending order."
+ (declare (pure t) (side-effect-free t))
+ (-find-indices (-partial 'equal elem) list))
+
+(defun -find-indices (pred list)
+ "Return the indices of all elements in LIST satisfying the
+predicate PRED, in ascending order."
+ (apply 'append (--map-indexed (when (funcall pred it) (list it-index)) list)))
+
+(defmacro --find-indices (form list)
+ "Anaphoric version of `-find-indices'."
+ (declare (debug (def-form form)))
+ `(-find-indices (lambda (it) ,form) ,list))
+
+(defun -find-index (pred list)
+ "Take a predicate PRED and a LIST and return the index of the
+first element in the list satisfying the predicate, or nil if
+there is no such element.
+
+See also `-first'."
+ (car (-find-indices pred list)))
+
+(defmacro --find-index (form list)
+ "Anaphoric version of `-find-index'."
+ (declare (debug (def-form form)))
+ `(-find-index (lambda (it) ,form) ,list))
+
+(defun -find-last-index (pred list)
+ "Take a predicate PRED and a LIST and return the index of the
+last element in the list satisfying the predicate, or nil if
+there is no such element.
+
+See also `-last'."
+ (-last-item (-find-indices pred list)))
+
+(defmacro --find-last-index (form list)
+ "Anaphoric version of `-find-last-index'."
+ (declare (debug (def-form form)))
+ `(-find-last-index (lambda (it) ,form) ,list))
+
+(defun -select-by-indices (indices list)
+ "Return a list whose elements are elements from LIST selected
+as `(nth i list)` for all i from INDICES."
+ (declare (pure t) (side-effect-free t))
+ (let (r)
+ (--each indices
+ (!cons (nth it list) r))
+ (nreverse r)))
+
+(defun -select-columns (columns table)
+ "Select COLUMNS from TABLE.
+
+TABLE is a list of lists where each element represents one row.
+It is assumed each row has the same length.
+
+Each row is transformed such that only the specified COLUMNS are
+selected.
+
+See also: `-select-column', `-select-by-indices'"
+ (declare (pure t) (side-effect-free t))
+ (--map (-select-by-indices columns it) table))
+
+(defun -select-column (column table)
+ "Select COLUMN from TABLE.
+
+TABLE is a list of lists where each element represents one row.
+It is assumed each row has the same length.
+
+The single selected column is returned as a list.
+
+See also: `-select-columns', `-select-by-indices'"
+ (declare (pure t) (side-effect-free t))
+ (--mapcat (-select-by-indices (list column) it) table))
+
+(defmacro -> (x &optional form &rest more)
+ "Thread the expr through the forms. Insert X as the second item
+in the first form, making a list of it if it is not a list
+already. If there are more forms, insert the first form as the
+second item in second form, etc."
+ (declare (debug (form &rest [&or symbolp (sexp &rest form)])))
+ (cond
+ ((null form) x)
+ ((null more) (if (listp form)
+ `(,(car form) ,x ,@(cdr form))
+ (list form x)))
+ (:else `(-> (-> ,x ,form) ,@more))))
+
+(defmacro ->> (x &optional form &rest more)
+ "Thread the expr through the forms. Insert X as the last item
+in the first form, making a list of it if it is not a list
+already. If there are more forms, insert the first form as the
+last item in second form, etc."
+ (declare (debug ->))
+ (cond
+ ((null form) x)
+ ((null more) (if (listp form)
+ `(,@form ,x)
+ (list form x)))
+ (:else `(->> (->> ,x ,form) ,@more))))
+
+(defmacro --> (x &rest forms)
+ "Starting with the value of X, thread each expression through FORMS.
+
+Insert X at the position signified by the symbol `it' in the first
+form. If there are more forms, insert the first form at the position
+signified by `it' in in second form, etc."
+ (declare (debug (form body)))
+ `(-as-> ,x it ,@forms))
+
+(defmacro -as-> (value variable &rest forms)
+ "Starting with VALUE, thread VARIABLE through FORMS.
+
+In the first form, bind VARIABLE to VALUE. In the second form, bind
+VARIABLE to the result of the first form, and so forth."
+ (declare (debug (form symbolp body)))
+ (if (null forms)
+ `,value
+ `(let ((,variable ,value))
+ (-as-> ,(if (symbolp (car forms))
+ (list (car forms) variable)
+ (car forms))
+ ,variable
+ ,@(cdr forms)))))
+
+(defmacro -some-> (x &optional form &rest more)
+ "When expr is non-nil, thread it through the first form (via `->'),
+and when that result is non-nil, through the next form, etc."
+ (declare (debug ->)
+ (indent 1))
+ (if (null form) x
+ (let ((result (make-symbol "result")))
+ `(-some-> (-when-let (,result ,x)
+ (-> ,result ,form))
+ ,@more))))
+
+(defmacro -some->> (x &optional form &rest more)
+ "When expr is non-nil, thread it through the first form (via `->>'),
+and when that result is non-nil, through the next form, etc."
+ (declare (debug ->)
+ (indent 1))
+ (if (null form) x
+ (let ((result (make-symbol "result")))
+ `(-some->> (-when-let (,result ,x)
+ (->> ,result ,form))
+ ,@more))))
+
+(defmacro -some--> (expr &rest forms)
+ "Thread EXPR through FORMS via `-->', while the result is non-nil.
+When EXPR evaluates to non-nil, thread the result through the
+first of FORMS, and when that result is non-nil, thread it
+through the next form, etc."
+ (declare (debug (form &rest &or symbolp consp)) (indent 1))
+ (if (null forms) expr
+ (let ((result (make-symbol "result")))
+ `(-some--> (-when-let (,result ,expr)
+ (--> ,result ,(car forms)))
+ ,@(cdr forms)))))
+
+(defmacro -doto (init &rest forms)
+ "Evaluate INIT and pass it as argument to FORMS with `->'.
+The RESULT of evaluating INIT is threaded through each of FORMS
+individually using `->', which see. The return value is RESULT,
+which FORMS may have modified by side effect."
+ (declare (debug (form &rest &or symbolp consp)) (indent 1))
+ (let ((retval (make-symbol "result")))
+ `(let ((,retval ,init))
+ ,@(mapcar (lambda (form) `(-> ,retval ,form)) forms)
+ ,retval)))
+
+(defmacro --doto (init &rest forms)
+ "Anaphoric form of `-doto'.
+This just evaluates INIT, binds the result to `it', evaluates
+FORMS, and returns the final value of `it'.
+Note: `it' need not be used in each form."
+ (declare (debug (form body)) (indent 1))
+ `(let ((it ,init))
+ ,@forms
+ it))
+
+(defun -grade-up (comparator list)
+ "Grade elements of LIST using COMPARATOR relation.
+This yields a permutation vector such that applying this
+permutation to LIST sorts it in ascending order."
+ (->> (--map-indexed (cons it it-index) list)
+ (-sort (lambda (it other) (funcall comparator (car it) (car other))))
+ (mapcar #'cdr)))
+
+(defun -grade-down (comparator list)
+ "Grade elements of LIST using COMPARATOR relation.
+This yields a permutation vector such that applying this
+permutation to LIST sorts it in descending order."
+ (->> (--map-indexed (cons it it-index) list)
+ (-sort (lambda (it other) (funcall comparator (car other) (car it))))
+ (mapcar #'cdr)))
+
+(defvar dash--source-counter 0
+ "Monotonic counter for generated symbols.")
+
+(defun dash--match-make-source-symbol ()
+ "Generate a new dash-source symbol.
+
+All returned symbols are guaranteed to be unique."
+ (prog1 (make-symbol (format "--dash-source-%d--" dash--source-counter))
+ (setq dash--source-counter (1+ dash--source-counter))))
+
+(defun dash--match-ignore-place-p (symbol)
+ "Return non-nil if SYMBOL is a symbol and starts with _."
+ (and (symbolp symbol)
+ (eq (aref (symbol-name symbol) 0) ?_)))
+
+(defun dash--match-cons-skip-cdr (skip-cdr source)
+ "Helper function generating idiomatic shifting code."
+ (cond
+ ((= skip-cdr 0)
+ `(pop ,source))
+ (t
+ `(prog1 ,(dash--match-cons-get-car skip-cdr source)
+ (setq ,source ,(dash--match-cons-get-cdr (1+ skip-cdr) source))))))
+
+(defun dash--match-cons-get-car (skip-cdr source)
+ "Helper function generating idiomatic code to get nth car."
+ (cond
+ ((= skip-cdr 0)
+ `(car ,source))
+ ((= skip-cdr 1)
+ `(cadr ,source))
+ (t
+ `(nth ,skip-cdr ,source))))
+
+(defun dash--match-cons-get-cdr (skip-cdr source)
+ "Helper function generating idiomatic code to get nth cdr."
+ (cond
+ ((= skip-cdr 0)
+ source)
+ ((= skip-cdr 1)
+ `(cdr ,source))
+ (t
+ `(nthcdr ,skip-cdr ,source))))
+
+(defun dash--match-cons (match-form source)
+ "Setup a cons matching environment and call the real matcher."
+ (let ((s (dash--match-make-source-symbol))
+ (n 0)
+ (m match-form))
+ (while (and (consp m)
+ (dash--match-ignore-place-p (car m)))
+ (setq n (1+ n)) (!cdr m))
+ (cond
+ ;; when we only have one pattern in the list, we don't have to
+ ;; create a temporary binding (--dash-source--) for the source
+ ;; and just use the input directly
+ ((and (consp m)
+ (not (cdr m)))
+ (dash--match (car m) (dash--match-cons-get-car n source)))
+ ;; handle other special types
+ ((> n 0)
+ (dash--match m (dash--match-cons-get-cdr n source)))
+ ;; this is the only entry-point for dash--match-cons-1, that's
+ ;; why we can't simply use the above branch, it would produce
+ ;; infinite recursion
+ (t
+ (cons (list s source) (dash--match-cons-1 match-form s))))))
+
+(defun dash--get-expand-function (type)
+ "Get expand function name for TYPE."
+ (intern-soft (format "dash-expand:%s" type)))
+
+(defun dash--match-cons-1 (match-form source &optional props)
+ "Match MATCH-FORM against SOURCE.
+
+MATCH-FORM is a proper or improper list. Each element of
+MATCH-FORM is either a symbol, which gets bound to the respective
+value in source or another match form which gets destructured
+recursively.
+
+If the cdr of last cons cell in the list is `nil', matching stops
+there.
+
+SOURCE is a proper or improper list."
+ (let ((skip-cdr (or (plist-get props :skip-cdr) 0)))
+ (cond
+ ((consp match-form)
+ (cond
+ ((cdr match-form)
+ (cond
+ ((and (symbolp (car match-form))
+ (functionp (dash--get-expand-function (car match-form))))
+ (dash--match-kv (dash--match-kv-normalize-match-form match-form) (dash--match-cons-get-cdr skip-cdr source)))
+ ((dash--match-ignore-place-p (car match-form))
+ (dash--match-cons-1 (cdr match-form) source
+ (plist-put props :skip-cdr (1+ skip-cdr))))
+ (t
+ (-concat (dash--match (car match-form) (dash--match-cons-skip-cdr skip-cdr source))
+ (dash--match-cons-1 (cdr match-form) source)))))
+ (t ;; Last matching place, no need for shift
+ (dash--match (car match-form) (dash--match-cons-get-car skip-cdr source)))))
+ ((eq match-form nil)
+ nil)
+ (t ;; Handle improper lists. Last matching place, no need for shift
+ (dash--match match-form (dash--match-cons-get-cdr skip-cdr source))))))
+
+(defun dash--match-vector (match-form source)
+ "Setup a vector matching environment and call the real matcher."
+ (let ((s (dash--match-make-source-symbol)))
+ (cond
+ ;; don't bind `s' if we only have one sub-pattern
+ ((= (length match-form) 1)
+ (dash--match (aref match-form 0) `(aref ,source 0)))
+ ;; if the source is a symbol, we don't need to re-bind it
+ ((symbolp source)
+ (dash--match-vector-1 match-form source))
+ ;; don't bind `s' if we only have one sub-pattern which is not ignored
+ ((let* ((ignored-places (mapcar 'dash--match-ignore-place-p match-form))
+ (ignored-places-n (length (-remove 'null ignored-places))))
+ (when (= ignored-places-n (1- (length match-form)))
+ (let ((n (-find-index 'null ignored-places)))
+ (dash--match (aref match-form n) `(aref ,source ,n))))))
+ (t
+ (cons (list s source) (dash--match-vector-1 match-form s))))))
+
+(defun dash--match-vector-1 (match-form source)
+ "Match MATCH-FORM against SOURCE.
+
+MATCH-FORM is a vector. Each element of MATCH-FORM is either a
+symbol, which gets bound to the respective value in source or
+another match form which gets destructured recursively.
+
+If second-from-last place in MATCH-FORM is the symbol &rest, the
+next element of the MATCH-FORM is matched against the tail of
+SOURCE, starting at index of the &rest symbol. This is
+conceptually the same as the (head . tail) match for improper
+lists, where dot plays the role of &rest.
+
+SOURCE is a vector.
+
+If the MATCH-FORM vector is shorter than SOURCE vector, only
+the (length MATCH-FORM) places are bound, the rest of the SOURCE
+is discarded."
+ (let ((i 0)
+ (l (length match-form))
+ (re))
+ (while (< i l)
+ (let ((m (aref match-form i)))
+ (push (cond
+ ((and (symbolp m)
+ (eq m '&rest))
+ (prog1 (dash--match
+ (aref match-form (1+ i))
+ `(substring ,source ,i))
+ (setq i l)))
+ ((and (symbolp m)
+ ;; do not match symbols starting with _
+ (not (eq (aref (symbol-name m) 0) ?_)))
+ (list (list m `(aref ,source ,i))))
+ ((not (symbolp m))
+ (dash--match m `(aref ,source ,i))))
+ re)
+ (setq i (1+ i))))
+ (-flatten-n 1 (nreverse re))))
+
+(defun dash--match-kv-normalize-match-form (pattern)
+ "Normalize kv PATTERN.
+
+This method normalizes PATTERN to the format expected by
+`dash--match-kv'. See `-let' for the specification."
+ (let ((normalized (list (car pattern)))
+ (skip nil)
+ (fill-placeholder (make-symbol "--dash-fill-placeholder--")))
+ (-each (apply '-zip (-pad fill-placeholder (cdr pattern) (cddr pattern)))
+ (lambda (pair)
+ (let ((current (car pair))
+ (next (cdr pair)))
+ (if skip
+ (setq skip nil)
+ (if (or (eq fill-placeholder next)
+ (not (or (and (symbolp next)
+ (not (keywordp next))
+ (not (eq next t))
+ (not (eq next nil)))
+ (and (consp next)
+ (not (eq (car next) 'quote)))
+ (vectorp next))))
+ (progn
+ (cond
+ ((keywordp current)
+ (push current normalized)
+ (push (intern (substring (symbol-name current) 1)) normalized))
+ ((stringp current)
+ (push current normalized)
+ (push (intern current) normalized))
+ ((and (consp current)
+ (eq (car current) 'quote))
+ (push current normalized)
+ (push (cadr current) normalized))
+ (t (error "-let: found key `%s' in kv destructuring but its pattern `%s' is invalid and can not be derived from the key" current next)))
+ (setq skip nil))
+ (push current normalized)
+ (push next normalized)
+ (setq skip t))))))
+ (nreverse normalized)))
+
+(defun dash--match-kv (match-form source)
+ "Setup a kv matching environment and call the real matcher.
+
+kv can be any key-value store, such as plist, alist or hash-table."
+ (let ((s (dash--match-make-source-symbol)))
+ (cond
+ ;; don't bind `s' if we only have one sub-pattern (&type key val)
+ ((= (length match-form) 3)
+ (dash--match-kv-1 (cdr match-form) source (car match-form)))
+ ;; if the source is a symbol, we don't need to re-bind it
+ ((symbolp source)
+ (dash--match-kv-1 (cdr match-form) source (car match-form)))
+ (t
+ (cons (list s source) (dash--match-kv-1 (cdr match-form) s (car match-form)))))))
+
+(defun dash-expand:&hash (key source)
+ "Generate extracting KEY from SOURCE for &hash destructuring."
+ `(gethash ,key ,source))
+
+(defun dash-expand:&plist (key source)
+ "Generate extracting KEY from SOURCE for &plist destructuring."
+ `(plist-get ,source ,key))
+
+(defun dash-expand:&alist (key source)
+ "Generate extracting KEY from SOURCE for &alist destructuring."
+ `(cdr (assoc ,key ,source)))
+
+(defun dash-expand:&hash? (key source)
+ "Generate extracting KEY from SOURCE for &hash? destructuring.
+Similar to &hash but check whether the map is not nil."
+ (let ((src (make-symbol "src")))
+ `(let ((,src ,source))
+ (when ,src (gethash ,key ,src)))))
+
+(defalias 'dash-expand:&keys 'dash-expand:&plist)
+
+(defun dash--match-kv-1 (match-form source type)
+ "Match MATCH-FORM against SOURCE of type TYPE.
+
+MATCH-FORM is a proper list of the form (key1 place1 ... keyN
+placeN). Each placeK is either a symbol, which gets bound to the
+value of keyK retrieved from the key-value store, or another
+match form which gets destructured recursively.
+
+SOURCE is a key-value store of type TYPE, which can be a plist,
+an alist or a hash table.
+
+TYPE is a token specifying the type of the key-value store.
+Valid values are &plist, &alist and &hash."
+ (-flatten-n 1 (-map
+ (lambda (kv)
+ (let* ((k (car kv))
+ (v (cadr kv))
+ (getter
+ (funcall (dash--get-expand-function type) k source)))
+ (cond
+ ((symbolp v)
+ (list (list v getter)))
+ (t (dash--match v getter)))))
+ (-partition 2 match-form))))
+
+(defun dash--match-symbol (match-form source)
+ "Bind a symbol.
+
+This works just like `let', there is no destructuring."
+ (list (list match-form source)))
+
+(defun dash--match (match-form source)
+ "Match MATCH-FORM against SOURCE.
+
+This function tests the MATCH-FORM and dispatches to specific
+matchers based on the type of the expression.
+
+Key-value stores are disambiguated by placing a token &plist,
+&alist or &hash as a first item in the MATCH-FORM."
+ (cond
+ ((symbolp match-form)
+ (dash--match-symbol match-form source))
+ ((consp match-form)
+ (cond
+ ;; Handle the "x &as" bindings first.
+ ((and (consp (cdr match-form))
+ (symbolp (car match-form))
+ (eq '&as (cadr match-form)))
+ (let ((s (car match-form)))
+ (cons (list s source)
+ (dash--match (cddr match-form) s))))
+ ((functionp (dash--get-expand-function (car match-form)))
+ (dash--match-kv (dash--match-kv-normalize-match-form match-form) source))
+ (t (dash--match-cons match-form source))))
+ ((vectorp match-form)
+ ;; We support the &as binding in vectors too
+ (cond
+ ((and (> (length match-form) 2)
+ (symbolp (aref match-form 0))
+ (eq '&as (aref match-form 1)))
+ (let ((s (aref match-form 0)))
+ (cons (list s source)
+ (dash--match (substring match-form 2) s))))
+ (t (dash--match-vector match-form source))))))
+
+(defun dash--normalize-let-varlist (varlist)
+ "Normalize VARLIST so that every binding is a list.
+
+`let' allows specifying a binding which is not a list but simply
+the place which is then automatically bound to nil, such that all
+three of the following are identical and evaluate to nil.
+
+ (let (a) a)
+ (let ((a)) a)
+ (let ((a nil)) a)
+
+This function normalizes all of these to the last form."
+ (--map (if (consp it) it (list it nil)) varlist))
+
+(defmacro -let* (varlist &rest body)
+ "Bind variables according to VARLIST then eval BODY.
+
+VARLIST is a list of lists of the form (PATTERN SOURCE). Each
+PATTERN is matched against the SOURCE structurally. SOURCE is
+only evaluated once for each PATTERN.
+
+Each SOURCE can refer to the symbols already bound by this
+VARLIST. This is useful if you want to destructure SOURCE
+recursively but also want to name the intermediate structures.
+
+See `-let' for the list of all possible patterns."
+ (declare (debug ((&rest [&or (sexp form) sexp]) body))
+ (indent 1))
+ (let* ((varlist (dash--normalize-let-varlist varlist))
+ (bindings (--mapcat (dash--match (car it) (cadr it)) varlist)))
+ `(let* ,bindings
+ ,@body)))
+
+(defmacro -let (varlist &rest body)
+ "Bind variables according to VARLIST then eval BODY.
+
+VARLIST is a list of lists of the form (PATTERN SOURCE). Each
+PATTERN is matched against the SOURCE \"structurally\". SOURCE
+is only evaluated once for each PATTERN. Each PATTERN is matched
+recursively, and can therefore contain sub-patterns which are
+matched against corresponding sub-expressions of SOURCE.
+
+All the SOURCEs are evalled before any symbols are
+bound (i.e. \"in parallel\").
+
+If VARLIST only contains one (PATTERN SOURCE) element, you can
+optionally specify it using a vector and discarding the
+outer-most parens. Thus
+
+ (-let ((PATTERN SOURCE)) ...)
+
+becomes
+
+ (-let [PATTERN SOURCE] ...).
+
+`-let' uses a convention of not binding places (symbols) starting
+with _ whenever it's possible. You can use this to skip over
+entries you don't care about. However, this is not *always*
+possible (as a result of implementation) and these symbols might
+get bound to undefined values.
+
+Following is the overview of supported patterns. Remember that
+patterns can be matched recursively, so every a, b, aK in the
+following can be a matching construct and not necessarily a
+symbol/variable.
+
+Symbol:
+
+ a - bind the SOURCE to A. This is just like regular `let'.
+
+Conses and lists:
+
+ (a) - bind `car' of cons/list to A
+
+ (a . b) - bind car of cons to A and `cdr' to B
+
+ (a b) - bind car of list to A and `cadr' to B
+
+ (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3...
+
+ (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST.
+
+Vectors:
+
+ [a] - bind 0th element of a non-list sequence to A (works with
+ vectors, strings, bit arrays...)
+
+ [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st to
+ A1, 2nd to A2, ...
+ If the PATTERN is shorter than SOURCE, the values at
+ places not in PATTERN are ignored.
+ If the PATTERN is longer than SOURCE, an `error' is
+ thrown.
+
+ [a1 a2 a3 ... &rest rest] - as above, but bind the rest of
+ the sequence to REST. This is
+ conceptually the same as improper list
+ matching (a1 a2 ... aN . rest)
+
+Key/value stores:
+
+ (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE plist to aK. If the
+ value is not found, aK is nil.
+ Uses `plist-get' to fetch values.
+
+ (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE alist to aK. If the
+ value is not found, aK is nil.
+ Uses `assoc' to fetch values.
+
+ (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE hash table to aK. If the
+ value is not found, aK is nil.
+ Uses `gethash' to fetch values.
+
+Further, special keyword &keys supports \"inline\" matching of
+plist-like key-value pairs, similarly to &keys keyword of
+`cl-defun'.
+
+ (a1 a2 ... aN &keys key1 b1 ... keyN bK)
+
+This binds N values from the list to a1 ... aN, then interprets
+the cdr as a plist (see key/value matching above).
+
+A shorthand notation for kv-destructuring exists which allows the
+patterns be optionally left out and derived from the key name in
+the following fashion:
+
+- a key :foo is converted into `foo' pattern,
+- a key 'bar is converted into `bar' pattern,
+- a key \"baz\" is converted into `baz' pattern.
+
+That is, the entire value under the key is bound to the derived
+variable without any further destructuring.
+
+This is possible only when the form following the key is not a
+valid pattern (i.e. not a symbol, a cons cell or a vector).
+Otherwise the matching proceeds as usual and in case of an
+invalid spec fails with an error.
+
+Thus the patterns are normalized as follows:
+
+ ;; derive all the missing patterns
+ (&plist :foo 'bar \"baz\") => (&plist :foo foo 'bar bar \"baz\" baz)
+
+ ;; we can specify some but not others
+ (&plist :foo 'bar explicit-bar) => (&plist :foo foo 'bar explicit-bar)
+
+ ;; nothing happens, we store :foo in x
+ (&plist :foo x) => (&plist :foo x)
+
+ ;; nothing happens, we match recursively
+ (&plist :foo (a b c)) => (&plist :foo (a b c))
+
+You can name the source using the syntax SYMBOL &as PATTERN.
+This syntax works with lists (proper or improper), vectors and
+all types of maps.
+
+ (list &as a b c) (list 1 2 3)
+
+binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
+
+Similarly:
+
+ (bounds &as beg . end) (cons 1 2)
+
+binds BEG to 1, END to 2 and BOUNDS to (1 . 2).
+
+ (items &as first . rest) (list 1 2 3)
+
+binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
+
+ [vect &as _ b c] [1 2 3]
+
+binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as usual).
+
+ (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and &hash.
+
+This is especially useful when we want to capture the result of a
+computation and destructure at the same time. Consider the
+form (function-returning-complex-structure) returning a list of
+two vectors with two items each. We want to capture this entire
+result and pass it to another computation, but at the same time
+we want to get the second item from each vector. We can achieve
+it with pattern
+
+ (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+Note: Clojure programmers may know this feature as the \":as
+binding\". The difference is that we put the &as at the front
+because we need to support improper list binding."
+ (declare (debug ([&or (&rest [&or (sexp form) sexp])
+ (vector [&rest [sexp form]])]
+ body))
+ (indent 1))
+ (if (vectorp varlist)
+ `(let* ,(dash--match (aref varlist 0) (aref varlist 1))
+ ,@body)
+ (let* ((varlist (dash--normalize-let-varlist varlist))
+ (inputs (--map-indexed (list (make-symbol (format "input%d" it-index)) (cadr it)) varlist))
+ (new-varlist (--map (list (caar it) (cadr it)) (-zip varlist inputs))))
+ `(let ,inputs
+ (-let* ,new-varlist ,@body)))))
+
+(defmacro -lambda (match-form &rest body)
+ "Return a lambda which destructures its input as MATCH-FORM and executes BODY.
+
+Note that you have to enclose the MATCH-FORM in a pair of parens,
+such that:
+
+ (-lambda (x) body)
+ (-lambda (x y ...) body)
+
+has the usual semantics of `lambda'. Furthermore, these get
+translated into normal `lambda', so there is no performance
+penalty.
+
+See `-let' for a description of the destructuring mechanism."
+ (declare (doc-string 2) (indent defun)
+ (debug (&define sexp
+ [&optional stringp]
+ [&optional ("interactive" interactive)]
+ def-body)))
+ (cond
+ ((nlistp match-form)
+ (signal 'wrong-type-argument (list #'listp match-form)))
+ ;; No destructuring, so just return regular `lambda' for speed.
+ ((-all? #'symbolp match-form)
+ `(lambda ,match-form ,@body))
+ ((let ((inputs (--map-indexed
+ (list it (make-symbol (format "input%d" it-index)))
+ match-form)))
+ ;; TODO: because inputs to the `lambda' are evaluated only once,
+ ;; `-let*' need not create the extra bindings to ensure that.
+ ;; We should find a way to optimize that. Not critical however.
+ `(lambda ,(mapcar #'cadr inputs)
+ (-let* ,inputs ,@body))))))
+
+(defmacro -setq (&rest forms)
+ "Bind each MATCH-FORM to the value of its VAL.
+
+MATCH-FORM destructuring is done according to the rules of `-let'.
+
+This macro allows you to bind multiple variables by destructuring
+the value, so for example:
+
+ (-setq (a b) x
+ (&plist :c c) plist)
+
+expands roughly speaking to the following code
+
+ (setq a (car x)
+ b (cadr x)
+ c (plist-get plist :c))
+
+Care is taken to only evaluate each VAL once so that in case of
+multiple assignments it does not cause unexpected side effects.
+
+\(fn [MATCH-FORM VAL]...)"
+ (declare (debug (&rest sexp form))
+ (indent 1))
+ (when (= (mod (length forms) 2) 1)
+ (signal 'wrong-number-of-arguments (list '-setq (1+ (length forms)))))
+ (let* ((forms-and-sources
+ ;; First get all the necessary mappings with all the
+ ;; intermediate bindings.
+ (-map (lambda (x) (dash--match (car x) (cadr x)))
+ (-partition 2 forms)))
+ ;; To preserve the logic of dynamic scoping we must ensure
+ ;; that we `setq' the variables outside of the `let*' form
+ ;; which holds the destructured intermediate values. For
+ ;; this we generate for each variable a placeholder which is
+ ;; bound to (lexically) the result of the destructuring.
+ ;; Then outside of the helper `let*' form we bind all the
+ ;; original variables to their respective placeholders.
+ ;; TODO: There is a lot of room for possible optimization,
+ ;; for start playing with `special-variable-p' to eliminate
+ ;; unnecessary re-binding.
+ (variables-to-placeholders
+ (-mapcat
+ (lambda (bindings)
+ (-map
+ (lambda (binding)
+ (let ((var (car binding)))
+ (list var (make-symbol (concat "--dash-binding-" (symbol-name var) "--")))))
+ (--filter (not (string-prefix-p "--" (symbol-name (car it)))) bindings)))
+ forms-and-sources)))
+ `(let ,(-map 'cadr variables-to-placeholders)
+ (let* ,(-flatten-n 1 forms-and-sources)
+ (setq ,@(-flatten (-map 'reverse variables-to-placeholders))))
+ (setq ,@(-flatten variables-to-placeholders)))))
+
+(defmacro -if-let* (vars-vals then &rest else)
+ "If all VALS evaluate to true, bind them to their corresponding
+VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list
+of (VAR VAL) pairs.
+
+Note: binding is done according to `-let*'. VALS are evaluated
+sequentially, and evaluation stops after the first nil VAL is
+encountered."
+ (declare (debug ((&rest (sexp form)) form body))
+ (indent 2))
+ (->> vars-vals
+ (--mapcat (dash--match (car it) (cadr it)))
+ (--reduce-r-from
+ (let ((var (car it))
+ (val (cadr it)))
+ `(let ((,var ,val))
+ (if ,var ,acc ,@else)))
+ then)))
+
+(defmacro -if-let (var-val then &rest else)
+ "If VAL evaluates to non-nil, bind it to VAR and do THEN,
+otherwise do ELSE.
+
+Note: binding is done according to `-let'.
+
+\(fn (VAR VAL) THEN &rest ELSE)"
+ (declare (debug ((sexp form) form body))
+ (indent 2))
+ `(-if-let* (,var-val) ,then ,@else))
+
+(defmacro --if-let (val then &rest else)
+ "If VAL evaluates to non-nil, bind it to symbol `it' and do THEN,
+otherwise do ELSE."
+ (declare (debug (form form body))
+ (indent 2))
+ `(-if-let (it ,val) ,then ,@else))
+
+(defmacro -when-let* (vars-vals &rest body)
+ "If all VALS evaluate to true, bind them to their corresponding
+VARS and execute body. VARS-VALS should be a list of (VAR VAL)
+pairs.
+
+Note: binding is done according to `-let*'. VALS are evaluated
+sequentially, and evaluation stops after the first nil VAL is
+encountered."
+ (declare (debug ((&rest (sexp form)) body))
+ (indent 1))
+ `(-if-let* ,vars-vals (progn ,@body)))
+
+(defmacro -when-let (var-val &rest body)
+ "If VAL evaluates to non-nil, bind it to VAR and execute body.
+
+Note: binding is done according to `-let'.
+
+\(fn (VAR VAL) &rest BODY)"
+ (declare (debug ((sexp form) body))
+ (indent 1))
+ `(-if-let ,var-val (progn ,@body)))
+
+(defmacro --when-let (val &rest body)
+ "If VAL evaluates to non-nil, bind it to symbol `it' and
+execute body."
+ (declare (debug (form body))
+ (indent 1))
+ `(--if-let ,val (progn ,@body)))
+
+(defvar -compare-fn nil
+ "Tests for equality use this function or `equal' if this is nil.
+It should only be set using dynamic scope with a let, like:
+
+ (let ((-compare-fn #\\='=)) (-union numbers1 numbers2 numbers3)")
+
+(defun -distinct (list)
+ "Return a new list with all duplicates removed.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil.
+
+Alias: `-uniq'"
+ ;; Implementation note: The speedup gained from hash table lookup
+ ;; starts to outweigh its overhead for lists of length greater than
+ ;; 32. See discussion in PR #305.
+ (let* ((len (length list))
+ (lut (and (> len 32)
+ ;; Check that `-compare-fn' is a valid hash-table
+ ;; lookup function or `nil'.
+ (memq -compare-fn '(nil equal eq eql))
+ (make-hash-table :test (or -compare-fn #'equal)
+ :size len))))
+ (if lut
+ (--filter (unless (gethash it lut)
+ (puthash it t lut))
+ list)
+ (--each list (unless (-contains? lut it) (!cons it lut)))
+ (nreverse lut))))
+
+(defalias '-uniq '-distinct)
+
+(defun -union (list list2)
+ "Return a new list containing the elements of LIST and elements of LIST2 that are not in LIST.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil."
+ ;; We fall back to iteration implementation if the comparison
+ ;; function isn't one of `eq', `eql' or `equal'.
+ (let* ((result (reverse list))
+ ;; TODO: get rid of this dynamic variable, pass it as an
+ ;; argument instead.
+ (-compare-fn (if (bound-and-true-p -compare-fn)
+ -compare-fn
+ 'equal)))
+ (if (memq -compare-fn '(eq eql equal))
+ (let ((ht (make-hash-table :test -compare-fn)))
+ (--each list (puthash it t ht))
+ (--each list2 (unless (gethash it ht) (!cons it result))))
+ (--each list2 (unless (-contains? result it) (!cons it result))))
+ (nreverse result)))
+
+(defun -intersection (list list2)
+ "Return a new list containing only the elements that are members of both LIST and LIST2.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil."
+ (--filter (-contains? list2 it) list))
+
+(defun -difference (list list2)
+ "Return a new list with only the members of LIST that are not in LIST2.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil."
+ (--filter (not (-contains? list2 it)) list))
+
+(defun -powerset (list)
+ "Return the power set of LIST."
+ (if (null list) '(())
+ (let ((last (-powerset (cdr list))))
+ (append (mapcar (lambda (x) (cons (car list) x)) last)
+ last))))
+
+(defun -permutations (list)
+ "Return the permutations of LIST."
+ (if (null list) '(())
+ (apply #'append
+ (mapcar (lambda (x)
+ (mapcar (lambda (perm) (cons x perm))
+ (-permutations (remove x list))))
+ list))))
+
+(defun -inits (list)
+ "Return all prefixes of LIST."
+ (let ((res (list list)))
+ (setq list (reverse list))
+ (while list
+ (push (reverse (!cdr list)) res))
+ res))
+
+(defun -tails (list)
+ "Return all suffixes of LIST"
+ (-reductions-r-from 'cons nil list))
+
+(defun -common-prefix (&rest lists)
+ "Return the longest common prefix of LISTS."
+ (declare (pure t) (side-effect-free t))
+ (--reduce (--take-while (and acc (equal (pop acc) it)) it)
+ lists))
+
+(defun -common-suffix (&rest lists)
+ "Return the longest common suffix of LISTS."
+ (nreverse (apply #'-common-prefix (mapcar #'reverse lists))))
+
+(defun -contains? (list element)
+ "Return non-nil if LIST contains ELEMENT.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that's non-nil.
+
+Alias: `-contains-p'"
+ (not
+ (null
+ (cond
+ ((null -compare-fn) (member element list))
+ ((eq -compare-fn 'eq) (memq element list))
+ ((eq -compare-fn 'eql) (memql element list))
+ (t
+ (let ((lst list))
+ (while (and lst
+ (not (funcall -compare-fn element (car lst))))
+ (setq lst (cdr lst)))
+ lst))))))
+
+(defalias '-contains-p '-contains?)
+
+(defun -same-items? (list list2)
+ "Return true if LIST and LIST2 has the same items.
+
+The order of the elements in the lists does not matter.
+
+Alias: `-same-items-p'"
+ (let ((length-a (length list))
+ (length-b (length list2)))
+ (and
+ (= length-a length-b)
+ (= length-a (length (-intersection list list2))))))
+
+(defalias '-same-items-p '-same-items?)
+
+(defun -is-prefix? (prefix list)
+ "Return non-nil if PREFIX is a prefix of LIST.
+
+Alias: `-is-prefix-p'."
+ (declare (pure t) (side-effect-free t))
+ (--each-while list (and (equal (car prefix) it)
+ (!cdr prefix)))
+ (null prefix))
+
+(defun -is-suffix? (suffix list)
+ "Return non-nil if SUFFIX is a suffix of LIST.
+
+Alias: `-is-suffix-p'."
+ (declare (pure t) (side-effect-free t))
+ (cond ((null suffix))
+ ((setq list (member (car suffix) list))
+ (equal (cdr suffix) (cdr list)))))
+
+(defun -is-infix? (infix list)
+ "Return non-nil if INFIX is infix of LIST.
+
+This operation runs in O(n^2) time
+
+Alias: `-is-infix-p'"
+ (declare (pure t) (side-effect-free t))
+ (let (done)
+ (while (and (not done) list)
+ (setq done (-is-prefix? infix list))
+ (!cdr list))
+ done))
+
+(defalias '-is-prefix-p '-is-prefix?)
+(defalias '-is-suffix-p '-is-suffix?)
+(defalias '-is-infix-p '-is-infix?)
+
+(defun -sort (comparator list)
+ "Sort LIST, stably, comparing elements using COMPARATOR.
+Return the sorted list. LIST is NOT modified by side effects.
+COMPARATOR is called with two elements of LIST, and should return non-nil
+if the first element should sort before the second."
+ (sort (copy-sequence list) comparator))
+
+(defmacro --sort (form list)
+ "Anaphoric form of `-sort'."
+ (declare (debug (def-form form)))
+ `(-sort (lambda (it other) ,form) ,list))
+
+(defun -list (&optional arg &rest args)
+ "Ensure ARG is a list.
+If ARG is already a list, return it as is (not a copy).
+Otherwise, return a new list with ARG as its only element.
+
+Another supported calling convention is (-list &rest ARGS).
+In this case, if ARG is not a list, a new list with all of
+ARGS as elements is returned. This use is supported for
+backward compatibility and is otherwise deprecated."
+ (declare (advertised-calling-convention (arg) "2.18.0")
+ (pure t) (side-effect-free t))
+ (if (listp arg) arg (cons arg args)))
+
+(defun -repeat (n x)
+ "Return a new list of length N with each element being X.
+Return nil if N is less than 1."
+ (declare (pure t) (side-effect-free t))
+ (and (natnump n) (make-list n x)))
+
+(defun -sum (list)
+ "Return the sum of LIST."
+ (declare (pure t) (side-effect-free t))
+ (apply '+ list))
+
+(defun -running-sum (list)
+ "Return a list with running sums of items in LIST.
+LIST must be non-empty."
+ (declare (pure t) (side-effect-free t))
+ (or list (signal 'wrong-type-argument (list #'consp list)))
+ (-reductions #'+ list))
+
+(defun -product (list)
+ "Return the product of LIST."
+ (declare (pure t) (side-effect-free t))
+ (apply '* list))
+
+(defun -running-product (list)
+ "Return a list with running products of items in LIST.
+LIST must be non-empty."
+ (declare (pure t) (side-effect-free t))
+ (or list (signal 'wrong-type-argument (list #'consp list)))
+ (-reductions #'* list))
+
+(defun -max (list)
+ "Return the largest value from LIST of numbers or markers."
+ (declare (pure t) (side-effect-free t))
+ (apply 'max list))
+
+(defun -min (list)
+ "Return the smallest value from LIST of numbers or markers."
+ (declare (pure t) (side-effect-free t))
+ (apply 'min list))
+
+(defun -max-by (comparator list)
+ "Take a comparison function COMPARATOR and a LIST and return
+the greatest element of the list by the comparison function.
+
+See also combinator `-on' which can transform the values before
+comparing them."
+ (--reduce (if (funcall comparator it acc) it acc) list))
+
+(defun -min-by (comparator list)
+ "Take a comparison function COMPARATOR and a LIST and return
+the least element of the list by the comparison function.
+
+See also combinator `-on' which can transform the values before
+comparing them."
+ (--reduce (if (funcall comparator it acc) acc it) list))
+
+(defmacro --max-by (form list)
+ "Anaphoric version of `-max-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+ (declare (debug (def-form form)))
+ `(-max-by (lambda (it other) ,form) ,list))
+
+(defmacro --min-by (form list)
+ "Anaphoric version of `-min-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+ (declare (debug (def-form form)))
+ `(-min-by (lambda (it other) ,form) ,list))
+
+(defun -iota (count &optional start step)
+ "Return a list containing COUNT numbers.
+Starts from START and adds STEP each time. The default START is
+zero, the default STEP is 1.
+This function takes its name from the corresponding primitive in
+the APL language."
+ (declare (pure t) (side-effect-free t))
+ (unless (natnump count)
+ (signal 'wrong-type-argument (list #'natnump count)))
+ (or start (setq start 0))
+ (or step (setq step 1))
+ (if (zerop step)
+ (make-list count start)
+ (--iterate (+ it step) start count)))
+
+(defun -fix (fn list)
+ "Compute the (least) fixpoint of FN with initial input LIST.
+
+FN is called at least once, results are compared with `equal'."
+ (let ((re (funcall fn list)))
+ (while (not (equal list re))
+ (setq list re)
+ (setq re (funcall fn re)))
+ re))
+
+(defmacro --fix (form list)
+ "Anaphoric form of `-fix'."
+ (declare (debug (def-form form)))
+ `(-fix (lambda (it) ,form) ,list))
+
+(defun -unfold (fun seed)
+ "Build a list from SEED using FUN.
+
+This is \"dual\" operation to `-reduce-r': while -reduce-r
+consumes a list to produce a single value, `-unfold' takes a
+seed value and builds a (potentially infinite!) list.
+
+FUN should return `nil' to stop the generating process, or a
+cons (A . B), where A will be prepended to the result and B is
+the new seed."
+ (let ((last (funcall fun seed)) r)
+ (while last
+ (push (car last) r)
+ (setq last (funcall fun (cdr last))))
+ (nreverse r)))
+
+(defmacro --unfold (form seed)
+ "Anaphoric version of `-unfold'."
+ (declare (debug (def-form form)))
+ `(-unfold (lambda (it) ,form) ,seed))
+
+(defun -cons-pair? (obj)
+ "Return non-nil if OBJ is a true cons pair.
+That is, a cons (A . B) where B is not a list.
+
+Alias: `-cons-pair-p'."
+ (declare (pure t) (side-effect-free t))
+ (nlistp (cdr-safe obj)))
+
+(defalias '-cons-pair-p '-cons-pair?)
+
+(defun -cons-to-list (con)
+ "Convert a cons pair to a list with `car' and `cdr' of the pair respectively."
+ (declare (pure t) (side-effect-free t))
+ (list (car con) (cdr con)))
+
+(defun -value-to-list (val)
+ "Convert a value to a list.
+
+If the value is a cons pair, make a list with two elements, `car'
+and `cdr' of the pair respectively.
+
+If the value is anything else, wrap it in a list."
+ (declare (pure t) (side-effect-free t))
+ (cond
+ ((-cons-pair? val) (-cons-to-list val))
+ (t (list val))))
+
+(defun -tree-mapreduce-from (fn folder init-value tree)
+ "Apply FN to each element of TREE, and make a list of the results.
+If elements of TREE are lists themselves, apply FN recursively to
+elements of these nested lists.
+
+Then reduce the resulting lists using FOLDER and initial value
+INIT-VALUE. See `-reduce-r-from'.
+
+This is the same as calling `-tree-reduce-from' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (-reduce-r-from folder init-value (mapcar (lambda (x) (-tree-mapreduce-from fn folder init-value x)) tree)))
+ (t (funcall fn tree))))
+
+(defmacro --tree-mapreduce-from (form folder init-value tree)
+ "Anaphoric form of `-tree-mapreduce-from'."
+ (declare (debug (def-form def-form form form)))
+ `(-tree-mapreduce-from (lambda (it) ,form) (lambda (it acc) ,folder) ,init-value ,tree))
+
+(defun -tree-mapreduce (fn folder tree)
+ "Apply FN to each element of TREE, and make a list of the results.
+If elements of TREE are lists themselves, apply FN recursively to
+elements of these nested lists.
+
+Then reduce the resulting lists using FOLDER and initial value
+INIT-VALUE. See `-reduce-r-from'.
+
+This is the same as calling `-tree-reduce' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x)) tree)))
+ (t (funcall fn tree))))
+
+(defmacro --tree-mapreduce (form folder tree)
+ "Anaphoric form of `-tree-mapreduce'."
+ (declare (debug (def-form def-form form)))
+ `(-tree-mapreduce (lambda (it) ,form) (lambda (it acc) ,folder) ,tree))
+
+(defun -tree-map (fn tree)
+ "Apply FN to each element of TREE while preserving the tree structure."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (mapcar (lambda (x) (-tree-map fn x)) tree))
+ (t (funcall fn tree))))
+
+(defmacro --tree-map (form tree)
+ "Anaphoric form of `-tree-map'."
+ (declare (debug (def-form form)))
+ `(-tree-map (lambda (it) ,form) ,tree))
+
+(defun -tree-reduce-from (fn init-value tree)
+ "Use FN to reduce elements of list TREE.
+If elements of TREE are lists themselves, apply the reduction recursively.
+
+FN is first applied to INIT-VALUE and first element of the list,
+then on this result and second element from the list etc.
+
+The initial value is ignored on cons pairs as they always contain
+two elements."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) tree)
+ ((listp tree)
+ (-reduce-r-from fn init-value (mapcar (lambda (x) (-tree-reduce-from fn init-value x)) tree)))
+ (t tree)))
+
+(defmacro --tree-reduce-from (form init-value tree)
+ "Anaphoric form of `-tree-reduce-from'."
+ (declare (debug (def-form form form)))
+ `(-tree-reduce-from (lambda (it acc) ,form) ,init-value ,tree))
+
+(defun -tree-reduce (fn tree)
+ "Use FN to reduce elements of list TREE.
+If elements of TREE are lists themselves, apply the reduction recursively.
+
+FN is first applied to first element of the list and second
+element, then on this result and third element from the list etc.
+
+See `-reduce-r' for how exactly are lists of zero or one element handled."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) tree)
+ ((listp tree)
+ (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree)))
+ (t tree)))
+
+(defmacro --tree-reduce (form tree)
+ "Anaphoric form of `-tree-reduce'."
+ (declare (debug (def-form form)))
+ `(-tree-reduce (lambda (it acc) ,form) ,tree))
+
+(defun -tree-map-nodes (pred fun tree)
+ "Call FUN on each node of TREE that satisfies PRED.
+
+If PRED returns nil, continue descending down this node. If PRED
+returns non-nil, apply FUN to this node and do not descend
+further."
+ (if (funcall pred tree)
+ (funcall fun tree)
+ (if (and (listp tree)
+ (not (-cons-pair? tree)))
+ (-map (lambda (x) (-tree-map-nodes pred fun x)) tree)
+ tree)))
+
+(defmacro --tree-map-nodes (pred form tree)
+ "Anaphoric form of `-tree-map-nodes'."
+ (declare (debug (def-form def-form form)))
+ `(-tree-map-nodes (lambda (it) ,pred) (lambda (it) ,form) ,tree))
+
+(defun -tree-seq (branch children tree)
+ "Return a sequence of the nodes in TREE, in depth-first search order.
+
+BRANCH is a predicate of one argument that returns non-nil if the
+passed argument is a branch, that is, a node that can have children.
+
+CHILDREN is a function of one argument that returns the children
+of the passed branch node.
+
+Non-branch nodes are simply copied."
+ (cons tree
+ (when (funcall branch tree)
+ (-mapcat (lambda (x) (-tree-seq branch children x))
+ (funcall children tree)))))
+
+(defmacro --tree-seq (branch children tree)
+ "Anaphoric form of `-tree-seq'."
+ (declare (debug (def-form def-form form)))
+ `(-tree-seq (lambda (it) ,branch) (lambda (it) ,children) ,tree))
+
+(defun -clone (list)
+ "Create a deep copy of LIST.
+The new list has the same elements and structure but all cons are
+replaced with new ones. This is useful when you need to clone a
+structure such as plist or alist."
+ (declare (pure t) (side-effect-free t))
+ (-tree-map 'identity list))
+
+;;; Combinators
+
+(defalias '-partial #'apply-partially)
+
+(defun -rpartial (fn &rest args)
+ "Return a function that is a partial application of FN to ARGS.
+ARGS is a list of the last N arguments to pass to FN. The result
+is a new function which does the same as FN, except that the last
+N arguments are fixed at the values with which this function was
+called. This is like `-partial', except the arguments are fixed
+starting from the right rather than the left."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args-before) (apply fn (append args-before args))))
+
+(defun -juxt (&rest fns)
+ "Return a function that is the juxtaposition of FNS.
+The returned function takes a variable number of ARGS, applies
+each of FNS in turn to ARGS, and returns the list of results."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns)))
+
+(defun -compose (&rest fns)
+ "Compose FNS into a single composite function.
+Return a function that takes a variable number of ARGS, applies
+the last function in FNS to ARGS, and returns the result of
+calling each remaining function on the result of the previous
+function, right-to-left. If no FNS are given, return a variadic
+`identity' function."
+ (declare (pure t) (side-effect-free t))
+ (let* ((fns (nreverse fns))
+ (head (car fns))
+ (tail (cdr fns)))
+ (cond (tail
+ (lambda (&rest args)
+ (--reduce-from (funcall it acc) (apply head args) tail)))
+ (fns head)
+ ((lambda (&optional arg &rest _) arg)))))
+
+(defun -applify (fn)
+ "Return a function that applies FN to a single list of args.
+This changes the arity of FN from taking N distinct arguments to
+taking 1 argument which is a list of N arguments."
+ (declare (pure t) (side-effect-free t))
+ (lambda (args) (apply fn args)))
+
+(defun -on (op trans)
+ "Return a function that calls TRANS on each arg and OP on the results.
+The returned function takes a variable number of arguments, calls
+the function TRANS on each one in turn, and then passes those
+results as the list of arguments to OP, in the same order.
+
+For example, the following pairs of expressions are morally
+equivalent:
+
+ (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
+ (funcall (-on #\\='+ #\\='1+)) = (+)"
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args)
+ ;; This unrolling seems to be a relatively cheap way to keep the
+ ;; overhead of `mapcar' + `apply' in check.
+ (cond ((cddr args)
+ (apply op (mapcar trans args)))
+ ((cdr args)
+ (funcall op (funcall trans (car args)) (funcall trans (cadr args))))
+ (args
+ (funcall op (funcall trans (car args))))
+ ((funcall op)))))
+
+(defun -flip (fn)
+ "Return a function that calls FN with its arguments reversed.
+The returned function takes the same number of arguments as FN.
+
+For example, the following two expressions are morally
+equivalent:
+
+ (funcall (-flip #\\='-) 1 2) = (- 2 1)
+
+See also: `-rotate-args'."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args) ;; Open-code for speed.
+ (cond ((cddr args) (apply fn (nreverse args)))
+ ((cdr args) (funcall fn (cadr args) (car args)))
+ (args (funcall fn (car args)))
+ ((funcall fn)))))
+
+(defun -rotate-args (n fn)
+ "Return a function that calls FN with args rotated N places to the right.
+The returned function takes the same number of arguments as FN,
+rotates the list of arguments N places to the right (left if N is
+negative) just like `-rotate', and applies FN to the result.
+
+See also: `-flip'."
+ (declare (pure t) (side-effect-free t))
+ (if (zerop n)
+ fn
+ (let ((even (= (% n 2) 0)))
+ (lambda (&rest args)
+ (cond ((cddr args) ;; Open-code for speed.
+ (apply fn (-rotate n args)))
+ ((cdr args)
+ (let ((fst (car args))
+ (snd (cadr args)))
+ (funcall fn (if even fst snd) (if even snd fst))))
+ (args
+ (funcall fn (car args)))
+ ((funcall fn)))))))
+
+(defun -const (c)
+ "Return a function that returns C ignoring any additional arguments.
+
+In types: a -> b -> a"
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest _) c))
+
+(defmacro -cut (&rest params)
+ "Take n-ary function and n arguments and specialize some of them.
+Arguments denoted by <> will be left unspecialized.
+
+See SRFI-26 for detailed description."
+ (declare (debug (&optional sexp &rest &or "<>" form)))
+ (let* ((i 0)
+ (args (--keep (when (eq it '<>)
+ (setq i (1+ i))
+ (make-symbol (format "D%d" i)))
+ params)))
+ `(lambda ,args
+ ,(let ((body (--map (if (eq it '<>) (pop args) it) params)))
+ (if (eq (car params) '<>)
+ (cons #'funcall body)
+ body)))))
+
+(defun -not (pred)
+ "Return a predicate that negates the result of PRED.
+The returned predicate passes its arguments to PRED. If PRED
+returns nil, the result is non-nil; otherwise the result is nil.
+
+See also: `-andfn' and `-orfn'."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args) (not (apply pred args))))
+
+(defun -orfn (&rest preds)
+ "Return a predicate that returns the first non-nil result of PREDS.
+The returned predicate takes a variable number of arguments,
+passes them to each predicate in PREDS in turn until one of them
+returns non-nil, and returns that non-nil result without calling
+the remaining PREDS. If all PREDS return nil, or if no PREDS are
+given, the returned predicate returns nil.
+
+See also: `-andfn' and `-not'."
+ (declare (pure t) (side-effect-free t))
+ ;; Open-code for speed.
+ (cond ((cdr preds) (lambda (&rest args) (--some (apply it args) preds)))
+ (preds (car preds))
+ (#'ignore)))
+
+(defun -andfn (&rest preds)
+ "Return a predicate that returns non-nil if all PREDS do so.
+The returned predicate P takes a variable number of arguments and
+passes them to each predicate in PREDS in turn. If any one of
+PREDS returns nil, P also returns nil without calling the
+remaining PREDS. If all PREDS return non-nil, P returns the last
+such value. If no PREDS are given, P always returns non-nil.
+
+See also: `-orfn' and `-not'."
+ (declare (pure t) (side-effect-free t))
+ ;; Open-code for speed.
+ (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds)))
+ (preds (car preds))
+ ;; As a `pure' function, this runtime check may generate
+ ;; backward-incompatible bytecode for `(-andfn)' at compile-time,
+ ;; but I doubt that's a problem in practice (famous last words).
+ ((fboundp 'always) #'always)
+ ((lambda (&rest _) t))))
+
+(defun -iteratefn (fn n)
+ "Return a function FN composed N times with itself.
+
+FN is a unary function. If you need to use a function of higher
+arity, use `-applify' first to turn it into a unary function.
+
+With n = 0, this acts as identity function.
+
+In types: (a -> a) -> Int -> a -> a.
+
+This function satisfies the following law:
+
+ (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n)))."
+ (lambda (x) (--dotimes n (setq x (funcall fn x))) x))
+
+(defun -counter (&optional beg end inc)
+ "Return a closure that counts from BEG to END, with increment INC.
+
+The closure will return the next value in the counting sequence
+each time it is called, and nil after END is reached. BEG
+defaults to 0, INC defaults to 1, and if END is nil, the counter
+will increment indefinitely.
+
+The closure accepts any number of arguments, which are discarded."
+ (let ((inc (or inc 1))
+ (n (or beg 0)))
+ (lambda (&rest _)
+ (when (or (not end) (< n end))
+ (prog1 n
+ (setq n (+ n inc)))))))
+
+(defvar -fixfn-max-iterations 1000
+ "The default maximum number of iterations performed by `-fixfn'
+ unless otherwise specified.")
+
+(defun -fixfn (fn &optional equal-test halt-test)
+ "Return a function that computes the (least) fixpoint of FN.
+
+FN must be a unary function. The returned lambda takes a single
+argument, X, the initial value for the fixpoint iteration. The
+iteration halts when either of the following conditions is satisfied:
+
+ 1. Iteration converges to the fixpoint, with equality being
+ tested using EQUAL-TEST. If EQUAL-TEST is not specified,
+ `equal' is used. For functions over the floating point
+ numbers, it may be necessary to provide an appropriate
+ approximate comparison test.
+
+ 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a
+ simple counter that returns t after `-fixfn-max-iterations',
+ to guard against infinite iteration. Otherwise, HALT-TEST
+ must be a function that accepts a single argument, the
+ current value of X, and returns non-nil as long as iteration
+ should continue. In this way, a more sophisticated
+ convergence test may be supplied by the caller.
+
+The return value of the lambda is either the fixpoint or, if
+iteration halted before converging, a cons with car `halted' and
+cdr the final output from HALT-TEST.
+
+In types: (a -> a) -> a -> a."
+ (let ((eqfn (or equal-test 'equal))
+ (haltfn (or halt-test
+ (-not
+ (-counter 0 -fixfn-max-iterations)))))
+ (lambda (x)
+ (let ((re (funcall fn x))
+ (halt? (funcall haltfn x)))
+ (while (and (not halt?) (not (funcall eqfn x re)))
+ (setq x re
+ re (funcall fn re)
+ halt? (funcall haltfn re)))
+ (if halt? (cons 'halted halt?)
+ re)))))
+
+(defun -prodfn (&rest fns)
+ "Take a list of n functions and return a function that takes a
+list of length n, applying i-th function to i-th element of the
+input list. Returns a list of length n.
+
+In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
+
+This function satisfies the following laws:
+
+ (-compose (-prodfn f g ...) (-prodfn f\\=' g\\=' ...)) = (-prodfn (-compose f f\\=') (-compose g g\\=') ...)
+ (-prodfn f g ...) = (-juxt (-compose f (-partial \\='nth 0)) (-compose g (-partial \\='nth 1)) ...)
+ (-compose (-prodfn f g ...) (-juxt f\\=' g\\=' ...)) = (-juxt (-compose f f\\=') (-compose g g\\=') ...)
+ (-compose (-partial \\='nth n) (-prod f1 f2 ...)) = (-compose fn (-partial \\='nth n))"
+ (lambda (x) (-zip-with 'funcall fns x)))
+
+;;; Font lock
+
+(defvar dash--keywords
+ `(;; TODO: Do not fontify the following automatic variables
+ ;; globally; detect and limit to their local anaphoric scope.
+ (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end)
+ 0 font-lock-variable-name-face)
+ ;; Macros in dev/examples.el. Based on `lisp-mode-symbol-regexp'.
+ (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end
+ (+ (in "\t "))
+ (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl)))))
+ (1 font-lock-keyword-face)
+ (2 font-lock-function-name-face))
+ ;; Symbols in dev/examples.el.
+ ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end)
+ ;; Elisp macro fontification was static prior to Emacs 25.
+ ,@(when (< emacs-major-version 25)
+ (let ((macs '("!cdr"
+ "!cons"
+ "-->"
+ "--all?"
+ "--annotate"
+ "--any?"
+ "--count"
+ "--dotimes"
+ "--doto"
+ "--drop-while"
+ "--each"
+ "--each-r"
+ "--each-r-while"
+ "--each-while"
+ "--filter"
+ "--find-index"
+ "--find-indices"
+ "--find-last-index"
+ "--first"
+ "--fix"
+ "--group-by"
+ "--if-let"
+ "--iterate"
+ "--keep"
+ "--last"
+ "--map"
+ "--map-first"
+ "--map-indexed"
+ "--map-last"
+ "--map-when"
+ "--mapcat"
+ "--max-by"
+ "--min-by"
+ "--none?"
+ "--only-some?"
+ "--partition-by"
+ "--partition-by-header"
+ "--reduce"
+ "--reduce-from"
+ "--reduce-r"
+ "--reduce-r-from"
+ "--reductions"
+ "--reductions-from"
+ "--reductions-r"
+ "--reductions-r-from"
+ "--remove"
+ "--remove-first"
+ "--remove-last"
+ "--separate"
+ "--some"
+ "--sort"
+ "--splice"
+ "--splice-list"
+ "--split-when"
+ "--split-with"
+ "--take-while"
+ "--tree-map"
+ "--tree-map-nodes"
+ "--tree-mapreduce"
+ "--tree-mapreduce-from"
+ "--tree-reduce"
+ "--tree-reduce-from"
+ "--tree-seq"
+ "--unfold"
+ "--update-at"
+ "--when-let"
+ "--zip-with"
+ "->"
+ "->>"
+ "-as->"
+ "-doto"
+ "-if-let"
+ "-if-let*"
+ "-lambda"
+ "-let"
+ "-let*"
+ "-setq"
+ "-some-->"
+ "-some->"
+ "-some->>"
+ "-split-on"
+ "-when-let"
+ "-when-let*")))
+ `((,(concat "(" (regexp-opt macs 'symbols)) . 1)))))
+ "Font lock keywords for `dash-fontify-mode'.")
+
+(defcustom dash-fontify-mode-lighter nil
+ "Mode line lighter for `dash-fontify-mode'.
+Either a string to display in the mode line when
+`dash-fontify-mode' is on, or nil to display
+nothing (the default)."
+ :package-version '(dash . "2.18.0")
+ :group 'dash
+ :type '(choice (string :tag "Lighter" :value " Dash")
+ (const :tag "Nothing" nil)))
+
+;;;###autoload
+(define-minor-mode dash-fontify-mode
+ "Toggle fontification of Dash special variables.
+
+Dash-Fontify mode is a buffer-local minor mode intended for Emacs
+Lisp buffers. Enabling it causes the special variables bound in
+anaphoric Dash macros to be fontified. These anaphoras include
+`it', `it-index', `acc', and `other'. In older Emacs versions
+which do not dynamically detect macros, Dash-Fontify mode
+additionally fontifies Dash macro calls.
+
+See also `dash-fontify-mode-lighter' and
+`global-dash-fontify-mode'."
+ :group 'dash :lighter dash-fontify-mode-lighter
+ (if dash-fontify-mode
+ (font-lock-add-keywords nil dash--keywords t)
+ (font-lock-remove-keywords nil dash--keywords))
+ (cond ((fboundp 'font-lock-flush) ;; Added in Emacs 25.
+ (font-lock-flush))
+ ;; `font-lock-fontify-buffer' unconditionally enables
+ ;; `font-lock-mode' and is marked `interactive-only' in later
+ ;; Emacs versions which have `font-lock-flush', so we guard
+ ;; and pacify as needed, respectively.
+ (font-lock-mode
+ (with-no-warnings
+ (font-lock-fontify-buffer)))))
+
+(defun dash--turn-on-fontify-mode ()
+ "Enable `dash-fontify-mode' if in an Emacs Lisp buffer."
+ (when (derived-mode-p #'emacs-lisp-mode)
+ (dash-fontify-mode)))
+
+;;;###autoload
+(define-globalized-minor-mode global-dash-fontify-mode
+ dash-fontify-mode dash--turn-on-fontify-mode
+ :group 'dash)
+
+(defcustom dash-enable-fontlock nil
+ "If non-nil, fontify Dash macro calls and special variables."
+ :group 'dash
+ :set (lambda (sym val)
+ (set-default sym val)
+ (global-dash-fontify-mode (if val 1 0)))
+ :type 'boolean)
+
+(make-obsolete-variable
+ 'dash-enable-fontlock #'global-dash-fontify-mode "2.18.0")
+
+(define-obsolete-function-alias
+ 'dash-enable-font-lock #'global-dash-fontify-mode "2.18.0")
+
+;;; Info
+
+(defvar dash--info-doc-spec '("(dash) Index" nil "^ -+ .*: " "\\( \\|$\\)")
+ "The Dash :doc-spec entry for `info-lookup-alist'.
+It is based on that for `emacs-lisp-mode'.")
+
+(defun dash--info-elisp-docs ()
+ "Return the `emacs-lisp-mode' symbol docs from `info-lookup-alist'.
+Specifically, return the cons containing their
+`info-lookup->doc-spec' so that we can modify it."
+ (defvar info-lookup-alist)
+ (nthcdr 3 (assq #'emacs-lisp-mode (cdr (assq 'symbol info-lookup-alist)))))
+
+;;;###autoload
+(defun dash-register-info-lookup ()
+ "Register the Dash Info manual with `info-lookup-symbol'.
+This allows Dash symbols to be looked up with \\[info-lookup-symbol]."
+ (interactive)
+ (require 'info-look)
+ (let ((docs (dash--info-elisp-docs)))
+ (setcar docs (append (car docs) (list dash--info-doc-spec)))
+ (info-lookup-reset)))
+
+(defun dash-unload-function ()
+ "Remove Dash from `info-lookup-alist'.
+Used by `unload-feature', which see."
+ (let ((docs (and (featurep 'info-look)
+ (dash--info-elisp-docs))))
+ (when (member dash--info-doc-spec (car docs))
+ (setcar docs (remove dash--info-doc-spec (car docs)))
+ (info-lookup-reset)))
+ nil)
+
+(provide 'dash)
+;;; dash.el ends here
diff --git a/emacs.d/elpa/dash-20210708.2009/dash.info b/emacs.d/elpa/dash-20210708.2009/dash.info
new file mode 100644
index 0000000..48c1af7
--- /dev/null
+++ b/emacs.d/elpa/dash-20210708.2009/dash.info
@@ -0,0 +1,4738 @@
+This is dash.info, produced by makeinfo version 6.7 from dash.texi.
+
+This manual is for Dash version 2.19.0.
+
+ Copyright © 2012–2021 Free Software Foundation, Inc.
+
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation License,
+ Version 1.3 or any later version published by the Free Software
+ Foundation; with the Invariant Sections being “GNU General Public
+ License,†and no Front-Cover Texts or Back-Cover Texts. A copy of
+ the license is included in the section entitled “GNU Free
+ Documentation Licenseâ€.
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* Dash: (dash.info). A modern list library for GNU Emacs.
+END-INFO-DIR-ENTRY
+
+
+File: dash.info, Node: Top, Next: Installation, Up: (dir)
+
+Dash
+****
+
+This manual is for Dash version 2.19.0.
+
+ Copyright © 2012–2021 Free Software Foundation, Inc.
+
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation License,
+ Version 1.3 or any later version published by the Free Software
+ Foundation; with the Invariant Sections being “GNU General Public
+ License,†and no Front-Cover Texts or Back-Cover Texts. A copy of
+ the license is included in the section entitled “GNU Free
+ Documentation Licenseâ€.
+
+* Menu:
+
+* Installation:: Installing and configuring Dash.
+* Functions:: Dash API reference.
+* Development:: Contributing to Dash development.
+
+Appendices
+
+* FDL:: The license for this documentation.
+* GPL:: Conditions for copying and changing Dash.
+* Index:: Index including functions and macros.
+
+ — The Detailed Node Listing —
+
+Installation
+
+* Using in a package:: Listing Dash as a package dependency.
+* Fontification of special variables:: Font Lock of anaphoric macro variables.
+* Info symbol lookup:: Looking up Dash symbols in this manual.
+
+Functions
+
+* Maps::
+* Sublist selection::
+* List to list::
+* Reductions::
+* Unfolding::
+* Predicates::
+* Partitioning::
+* Indexing::
+* Set operations::
+* Other list operations::
+* Tree operations::
+* Threading macros::
+* Binding::
+* Side effects::
+* Destructive operations::
+* Function combinators::
+
+Development
+
+* Contribute:: How to contribute.
+* Contributors:: List of contributors.
+
+
+File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top
+
+1 Installation
+**************
+
+Dash is available on GNU ELPA (https://elpa.gnu.org/), GNU-devel ELPA
+(https://elpa.gnu.org/devel/), and MELPA (https://melpa.org/), and can
+be installed with the standard command ‘package-install’ (*note
+(emacs)Package Installation::).
+
+‘M-x package-install <RET> dash <RET>’
+ Install the Dash library.
+
+ Alternatively, you can just dump ‘dash.el’ in your ‘load-path’
+somewhere (*note (emacs)Lisp Libraries::).
+
+* Menu:
+
+* Using in a package:: Listing Dash as a package dependency.
+* Fontification of special variables:: Font Lock of anaphoric macro variables.
+* Info symbol lookup:: Looking up Dash symbols in this manual.
+
+
+File: dash.info, Node: Using in a package, Next: Fontification of special variables, Up: Installation
+
+1.1 Using in a package
+======================
+
+If you use Dash in your own package, be sure to list it as a dependency
+in the library’s headers as follows (*note (elisp)Library Headers::).
+
+ ;; Package-Requires: ((dash "2.19.0"))
+
+
+File: dash.info, Node: Fontification of special variables, Next: Info symbol lookup, Prev: Using in a package, Up: Installation
+
+1.2 Fontification of special variables
+======================================
+
+The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional
+fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs
+Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::).
+In older Emacs versions which do not dynamically detect macros, the
+minor mode also fontifies calls to Dash macros.
+
+ To automatically enable the minor mode in all Emacs Lisp buffers,
+just call its autoloaded global counterpart ‘global-dash-fontify-mode’,
+either interactively or from your ‘user-init-file’:
+
+ (global-dash-fontify-mode)
+
+
+File: dash.info, Node: Info symbol lookup, Prev: Fontification of special variables, Up: Installation
+
+1.3 Info symbol lookup
+======================
+
+While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to
+look up Elisp symbols in the relevant Info manuals (*note (emacs)Info
+Lookup::). To enable the same for Dash symbols, use the command
+‘dash-register-info-lookup’. It can be called directly when needed, or
+automatically from your ‘user-init-file’. For example:
+
+ (with-eval-after-load 'info-look
+ (dash-register-info-lookup))
+
+
+File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top
+
+2 Functions
+***********
+
+This chapter contains reference documentation for the Dash API
+(Application Programming Interface). The names of all public functions
+defined in the library are prefixed with a dash character (‘-’).
+
+ The library also provides anaphoric macro versions of functions where
+that makes sense. The names of these macros are prefixed with two
+dashes (‘--’) instead of one.
+
+ For instance, while the function ‘-map’ applies a function to each
+element of a list, its anaphoric counterpart ‘--map’ evaluates a form
+with the local variable ‘it’ temporarily bound to the current list
+element instead.
+
+ ;; Normal version.
+ (-map (lambda (n) (* n n)) '(1 2 3 4))
+ ⇒ (1 4 9 16)
+
+ ;; Anaphoric version.
+ (--map (* it it) '(1 2 3 4))
+ ⇒ (1 4 9 16)
+
+ The normal version can, of course, also be written as in the
+following example, which demonstrates the utility of both versions.
+
+ (defun my-square (n)
+ "Return N multiplied by itself."
+ (* n n))
+
+ (-map #'my-square '(1 2 3 4))
+ ⇒ (1 4 9 16)
+
+* Menu:
+
+* Maps::
+* Sublist selection::
+* List to list::
+* Reductions::
+* Unfolding::
+* Predicates::
+* Partitioning::
+* Indexing::
+* Set operations::
+* Other list operations::
+* Tree operations::
+* Threading macros::
+* Binding::
+* Side effects::
+* Destructive operations::
+* Function combinators::
+
+
+File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions
+
+2.1 Maps
+========
+
+Functions in this category take a transforming function, which is then
+applied sequentially to each or selected elements of the input list.
+The results are collected in order and returned as a new list.
+
+ -- Function: -map (fn list)
+ Apply FN to each item in LIST and return the list of results.
+
+ This function’s anaphoric counterpart is ‘--map’.
+
+ (-map (lambda (num) (* num num)) '(1 2 3 4))
+ ⇒ (1 4 9 16)
+ (-map #'1+ '(1 2 3 4))
+ ⇒ (2 3 4 5)
+ (--map (* it it) '(1 2 3 4))
+ ⇒ (1 4 9 16)
+
+ -- Function: -map-when (pred rep list)
+ Return a new list where the elements in LIST that do not match the
+ PRED function are unchanged, and where the elements in LIST that do
+ match the PRED function are mapped through the REP function.
+
+ Alias: ‘-replace-where’
+
+ See also: ‘-update-at’ (*note -update-at::)
+
+ (-map-when 'even? 'square '(1 2 3 4))
+ ⇒ (1 4 3 16)
+ (--map-when (> it 2) (* it it) '(1 2 3 4))
+ ⇒ (1 2 9 16)
+ (--map-when (= it 2) 17 '(1 2 3 4))
+ ⇒ (1 17 3 4)
+
+ -- Function: -map-first (pred rep list)
+ Replace first item in LIST satisfying PRED with result of REP
+ called on this item.
+
+ See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note
+ -replace-first::)
+
+ (-map-first 'even? 'square '(1 2 3 4))
+ ⇒ (1 4 3 4)
+ (--map-first (> it 2) (* it it) '(1 2 3 4))
+ ⇒ (1 2 9 4)
+ (--map-first (= it 2) 17 '(1 2 3 2))
+ ⇒ (1 17 3 2)
+
+ -- Function: -map-last (pred rep list)
+ Replace last item in LIST satisfying PRED with result of REP called
+ on this item.
+
+ See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note
+ -replace-last::)
+
+ (-map-last 'even? 'square '(1 2 3 4))
+ ⇒ (1 2 3 16)
+ (--map-last (> it 2) (* it it) '(1 2 3 4))
+ ⇒ (1 2 3 16)
+ (--map-last (= it 2) 17 '(1 2 3 2))
+ ⇒ (1 2 3 17)
+
+ -- Function: -map-indexed (fn list)
+ Apply FN to each index and item in LIST and return the list of
+ results. This is like ‘-map’ (*note -map::), but FN takes two
+ arguments: the index of the current element within LIST, and the
+ element itself.
+
+ This function’s anaphoric counterpart is ‘--map-indexed’.
+
+ For a side-effecting variant, see also ‘-each-indexed’ (*note
+ -each-indexed::).
+
+ (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4))
+ ⇒ (1 1 1 1)
+ (--map-indexed (- it it-index) '(1 2 3 4))
+ ⇒ (1 1 1 1)
+ (-map-indexed #'* '(1 2 3 4))
+ ⇒ (0 2 6 12)
+
+ -- Function: -annotate (fn list)
+ Return a list of cons cells where each cell is FN applied to each
+ element of LIST paired with the unmodified element of LIST.
+
+ (-annotate '1+ '(1 2 3))
+ ⇒ ((2 . 1) (3 . 2) (4 . 3))
+ (-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world")))
+ ⇒ ((5 "h" "e" "l" "l" "o") (2 "hello" "world"))
+ (--annotate (< 1 it) '(0 1 2 3))
+ ⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3))
+
+ -- Function: -splice (pred fun list)
+ Splice lists generated by FUN in place of elements matching PRED in
+ LIST.
+
+ FUN takes the element matching PRED as input.
+
+ This function can be used as replacement for ‘,@’ in case you need
+ to splice several lists at marked positions (for example with
+ keywords).
+
+ See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’
+ (*note -insert-at::)
+
+ (-splice 'even? (lambda (x) (list x x)) '(1 2 3 4))
+ ⇒ (1 2 2 3 4 4)
+ (--splice 't (list it it) '(1 2 3 4))
+ ⇒ (1 1 2 2 3 3 4 4)
+ (--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz)))
+ ⇒ ((foo) (bar) (list of) (magical) (code) (baz))
+
+ -- Function: -splice-list (pred new-list list)
+ Splice NEW-LIST in place of elements matching PRED in LIST.
+
+ See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note
+ -insert-at::)
+
+ (-splice-list 'keywordp '(a b c) '(1 :foo 2))
+ ⇒ (1 a b c 2)
+ (-splice-list 'keywordp nil '(1 :foo 2))
+ ⇒ (1 2)
+ (--splice-list (keywordp it) '(a b c) '(1 :foo 2))
+ ⇒ (1 a b c 2)
+
+ -- Function: -mapcat (fn list)
+ Return the concatenation of the result of mapping FN over LIST.
+ Thus function FN should return a list.
+
+ (-mapcat 'list '(1 2 3))
+ ⇒ (1 2 3)
+ (-mapcat (lambda (item) (list 0 item)) '(1 2 3))
+ ⇒ (0 1 0 2 0 3)
+ (--mapcat (list 0 it) '(1 2 3))
+ ⇒ (0 1 0 2 0 3)
+
+ -- Function: -copy (list)
+ Create a shallow copy of LIST.
+
+ (-copy '(1 2 3))
+ ⇒ (1 2 3)
+ (let ((a '(1 2 3))) (eq a (-copy a)))
+ ⇒ nil
+
+
+File: dash.info, Node: Sublist selection, Next: List to list, Prev: Maps, Up: Functions
+
+2.2 Sublist selection
+=====================
+
+Functions returning a sublist of the original list.
+
+ -- Function: -filter (pred list)
+ Return a new list of the items in LIST for which PRED returns
+ non-nil.
+
+ Alias: ‘-select’.
+
+ This function’s anaphoric counterpart is ‘--filter’.
+
+ For similar operations, see also ‘-keep’ (*note -keep::) and
+ ‘-remove’ (*note -remove::).
+
+ (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
+ ⇒ (2 4)
+ (-filter #'natnump '(-2 -1 0 1 2))
+ ⇒ (0 1 2)
+ (--filter (= 0 (% it 2)) '(1 2 3 4))
+ ⇒ (2 4)
+
+ -- Function: -remove (pred list)
+ Return a new list of the items in LIST for which PRED returns nil.
+
+ Alias: ‘-reject’.
+
+ This function’s anaphoric counterpart is ‘--remove’.
+
+ For similar operations, see also ‘-keep’ (*note -keep::) and
+ ‘-filter’ (*note -filter::).
+
+ (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
+ ⇒ (1 3)
+ (-remove #'natnump '(-2 -1 0 1 2))
+ ⇒ (-2 -1)
+ (--remove (= 0 (% it 2)) '(1 2 3 4))
+ ⇒ (1 3)
+
+ -- Function: -remove-first (pred list)
+ Remove the first item from LIST for which PRED returns non-nil.
+ This is a non-destructive operation, but only the front of LIST
+ leading up to the removed item is a copy; the rest is LIST’s
+ original tail. If no item is removed, then the result is a
+ complete copy.
+
+ Alias: ‘-reject-first’.
+
+ This function’s anaphoric counterpart is ‘--remove-first’.
+
+ See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note
+ -remove-item::), and ‘-remove-last’ (*note -remove-last::).
+
+ (-remove-first #'natnump '(-2 -1 0 1 2))
+ ⇒ (-2 -1 1 2)
+ (-remove-first #'stringp '(1 2 "first" "second"))
+ ⇒ (1 2 "second")
+ (--remove-first (> it 3) '(1 2 3 4 5 6))
+ ⇒ (1 2 3 5 6)
+
+ -- Function: -remove-last (pred list)
+ Remove the last item from LIST for which PRED returns non-nil. The
+ result is a copy of LIST regardless of whether an element is
+ removed.
+
+ Alias: ‘-reject-last’.
+
+ This function’s anaphoric counterpart is ‘--remove-last’.
+
+ See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note
+ -remove-item::), and ‘-remove-first’ (*note -remove-first::).
+
+ (-remove-last #'natnump '(1 3 5 4 7 8 10 -11))
+ ⇒ (1 3 5 4 7 8 -11)
+ (-remove-last #'stringp '(1 2 "last" "second"))
+ ⇒ (1 2 "last")
+ (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10))
+ ⇒ (1 2 3 4 5 6 7 8 9)
+
+ -- Function: -remove-item (item list)
+ Return a copy of LIST with all occurrences of ITEM removed. The
+ comparison is done with ‘equal’.
+
+ (-remove-item 3 '(1 2 3 2 3 4 5 3))
+ ⇒ (1 2 2 4 5)
+ (-remove-item 'foo '(foo bar baz foo))
+ ⇒ (bar baz)
+ (-remove-item "bob" '("alice" "bob" "eve" "bob"))
+ ⇒ ("alice" "eve")
+
+ -- Function: -non-nil (list)
+ Return a copy of LIST with all nil items removed.
+
+ (-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil))
+ ⇒ (1 2 3 4 5)
+ (-non-nil '((nil)))
+ ⇒ ((nil))
+ (-non-nil ())
+ ⇒ ()
+
+ -- Function: -slice (list from &optional to step)
+ Return copy of LIST, starting from index FROM to index TO.
+
+ FROM or TO may be negative. These values are then interpreted
+ modulo the length of the list.
+
+ If STEP is a number, only each STEPth item in the resulting section
+ is returned. Defaults to 1.
+
+ (-slice '(1 2 3 4 5) 1)
+ ⇒ (2 3 4 5)
+ (-slice '(1 2 3 4 5) 0 3)
+ ⇒ (1 2 3)
+ (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2)
+ ⇒ (2 4 6 8)
+
+ -- Function: -take (n list)
+ Return a copy of the first N items in LIST. Return a copy of LIST
+ if it contains N items or fewer. Return nil if N is zero or less.
+
+ See also: ‘-take-last’ (*note -take-last::).
+
+ (-take 3 '(1 2 3 4 5))
+ ⇒ (1 2 3)
+ (-take 17 '(1 2 3 4 5))
+ ⇒ (1 2 3 4 5)
+ (-take 0 '(1 2 3 4 5))
+ ⇒ ()
+
+ -- Function: -take-last (n list)
+ Return a copy of the last N items of LIST in order. Return a copy
+ of LIST if it contains N items or fewer. Return nil if N is zero
+ or less.
+
+ See also: ‘-take’ (*note -take::).
+
+ (-take-last 3 '(1 2 3 4 5))
+ ⇒ (3 4 5)
+ (-take-last 17 '(1 2 3 4 5))
+ ⇒ (1 2 3 4 5)
+ (-take-last 1 '(1 2 3 4 5))
+ ⇒ (5)
+
+ -- Function: -drop (n list)
+ Return the tail (not a copy) of LIST without the first N items.
+ Return nil if LIST contains N items or fewer. Return LIST if N is
+ zero or less.
+
+ For another variant, see also ‘-drop-last’ (*note -drop-last::).
+
+ (-drop 3 '(1 2 3 4 5))
+ ⇒ (4 5)
+ (-drop 17 '(1 2 3 4 5))
+ ⇒ ()
+ (-drop 0 '(1 2 3 4 5))
+ ⇒ (1 2 3 4 5)
+
+ -- Function: -drop-last (n list)
+ Return a copy of LIST without its last N items. Return a copy of
+ LIST if N is zero or less. Return nil if LIST contains N items or
+ fewer.
+
+ See also: ‘-drop’ (*note -drop::).
+
+ (-drop-last 3 '(1 2 3 4 5))
+ ⇒ (1 2)
+ (-drop-last 17 '(1 2 3 4 5))
+ ⇒ ()
+ (-drop-last 0 '(1 2 3 4 5))
+ ⇒ (1 2 3 4 5)
+
+ -- Function: -take-while (pred list)
+ Take successive items from LIST for which PRED returns non-nil.
+ PRED is a function of one argument. Return a new list of the
+ successive elements from the start of LIST for which PRED returns
+ non-nil.
+
+ This function’s anaphoric counterpart is ‘--take-while’.
+
+ For another variant, see also ‘-drop-while’ (*note -drop-while::).
+
+ (-take-while #'even? '(1 2 3 4))
+ ⇒ ()
+ (-take-while #'even? '(2 4 5 6))
+ ⇒ (2 4)
+ (--take-while (< it 4) '(1 2 3 4 3 2 1))
+ ⇒ (1 2 3)
+
+ -- Function: -drop-while (pred list)
+ Drop successive items from LIST for which PRED returns non-nil.
+ PRED is a function of one argument. Return the tail (not a copy)
+ of LIST starting from its first element for which PRED returns nil.
+
+ This function’s anaphoric counterpart is ‘--drop-while’.
+
+ For another variant, see also ‘-take-while’ (*note -take-while::).
+
+ (-drop-while #'even? '(1 2 3 4))
+ ⇒ (1 2 3 4)
+ (-drop-while #'even? '(2 4 5 6))
+ ⇒ (5 6)
+ (--drop-while (< it 4) '(1 2 3 4 3 2 1))
+ ⇒ (4 3 2 1)
+
+ -- Function: -select-by-indices (indices list)
+ Return a list whose elements are elements from LIST selected as
+ ‘(nth i list)‘ for all i from INDICES.
+
+ (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r"))
+ ⇒ ("c" "o" "l" "o" "r")
+ (-select-by-indices '(2 1 0) '("a" "b" "c"))
+ ⇒ ("c" "b" "a")
+ (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l"))
+ ⇒ ("f" "a" "r" "f" "a" "l" "l" "a")
+
+ -- Function: -select-columns (columns table)
+ Select COLUMNS from TABLE.
+
+ TABLE is a list of lists where each element represents one row. It
+ is assumed each row has the same length.
+
+ Each row is transformed such that only the specified COLUMNS are
+ selected.
+
+ See also: ‘-select-column’ (*note -select-column::),
+ ‘-select-by-indices’ (*note -select-by-indices::)
+
+ (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c)))
+ ⇒ ((1 3) (a c) (:a :c))
+ (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c)))
+ ⇒ ((2) (b) (:b))
+ (-select-columns nil '((1 2 3) (a b c) (:a :b :c)))
+ ⇒ (nil nil nil)
+
+ -- Function: -select-column (column table)
+ Select COLUMN from TABLE.
+
+ TABLE is a list of lists where each element represents one row. It
+ is assumed each row has the same length.
+
+ The single selected column is returned as a list.
+
+ See also: ‘-select-columns’ (*note -select-columns::),
+ ‘-select-by-indices’ (*note -select-by-indices::)
+
+ (-select-column 1 '((1 2 3) (a b c) (:a :b :c)))
+ ⇒ (2 b :b)
+
+
+File: dash.info, Node: List to list, Next: Reductions, Prev: Sublist selection, Up: Functions
+
+2.3 List to list
+================
+
+Functions returning a modified copy of the input list.
+
+ -- Function: -keep (fn list)
+ Return a new list of the non-nil results of applying FN to each
+ item in LIST. Like ‘-filter’ (*note -filter::), but returns the
+ non-nil results of FN instead of the corresponding elements of
+ LIST.
+
+ Its anaphoric counterpart is ‘--keep’.
+
+ (-keep #'cdr '((1 2 3) (4 5) (6)))
+ ⇒ ((2 3) (5))
+ (-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6))
+ ⇒ (40 50 60)
+ (--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6))
+ ⇒ (40 50 60)
+
+ -- Function: -concat (&rest lists)
+ Return a new list with the concatenation of the elements in the
+ supplied LISTS.
+
+ (-concat '(1))
+ ⇒ (1)
+ (-concat '(1) '(2))
+ ⇒ (1 2)
+ (-concat '(1) '(2 3) '(4))
+ ⇒ (1 2 3 4)
+
+ -- Function: -flatten (l)
+ Take a nested list L and return its contents as a single, flat
+ list.
+
+ Note that because ‘nil’ represents a list of zero elements (an
+ empty list), any mention of nil in L will disappear after
+ flattening. If you need to preserve nils, consider ‘-flatten-n’
+ (*note -flatten-n::) or map them to some unique symbol and then map
+ them back.
+
+ Conses of two atoms are considered "terminals", that is, they
+ aren’t flattened further.
+
+ See also: ‘-flatten-n’ (*note -flatten-n::)
+
+ (-flatten '((1)))
+ ⇒ (1)
+ (-flatten '((1 (2 3) (((4 (5)))))))
+ ⇒ (1 2 3 4 5)
+ (-flatten '(1 2 (3 . 4)))
+ ⇒ (1 2 (3 . 4))
+
+ -- Function: -flatten-n (num list)
+ Flatten NUM levels of a nested LIST.
+
+ See also: ‘-flatten’ (*note -flatten::)
+
+ (-flatten-n 1 '((1 2) ((3 4) ((5 6)))))
+ ⇒ (1 2 (3 4) ((5 6)))
+ (-flatten-n 2 '((1 2) ((3 4) ((5 6)))))
+ ⇒ (1 2 3 4 (5 6))
+ (-flatten-n 3 '((1 2) ((3 4) ((5 6)))))
+ ⇒ (1 2 3 4 5 6)
+
+ -- Function: -replace (old new list)
+ Replace all OLD items in LIST with NEW.
+
+ Elements are compared using ‘equal’.
+
+ See also: ‘-replace-at’ (*note -replace-at::)
+
+ (-replace 1 "1" '(1 2 3 4 3 2 1))
+ ⇒ ("1" 2 3 4 3 2 "1")
+ (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+ ⇒ ("a" "nice" "bar" "sentence" "about" "bar")
+ (-replace 1 2 nil)
+ ⇒ nil
+
+ -- Function: -replace-first (old new list)
+ Replace the first occurrence of OLD with NEW in LIST.
+
+ Elements are compared using ‘equal’.
+
+ See also: ‘-map-first’ (*note -map-first::)
+
+ (-replace-first 1 "1" '(1 2 3 4 3 2 1))
+ ⇒ ("1" 2 3 4 3 2 1)
+ (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+ ⇒ ("a" "nice" "bar" "sentence" "about" "foo")
+ (-replace-first 1 2 nil)
+ ⇒ nil
+
+ -- Function: -replace-last (old new list)
+ Replace the last occurrence of OLD with NEW in LIST.
+
+ Elements are compared using ‘equal’.
+
+ See also: ‘-map-last’ (*note -map-last::)
+
+ (-replace-last 1 "1" '(1 2 3 4 3 2 1))
+ ⇒ (1 2 3 4 3 2 "1")
+ (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+ ⇒ ("a" "nice" "foo" "sentence" "about" "bar")
+ (-replace-last 1 2 nil)
+ ⇒ nil
+
+ -- Function: -insert-at (n x list)
+ Return a list with X inserted into LIST at position N.
+
+ See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note
+ -splice-list::)
+
+ (-insert-at 1 'x '(a b c))
+ ⇒ (a x b c)
+ (-insert-at 12 'x '(a b c))
+ ⇒ (a b c x)
+
+ -- Function: -replace-at (n x list)
+ Return a list with element at Nth position in LIST replaced with X.
+
+ See also: ‘-replace’ (*note -replace::)
+
+ (-replace-at 0 9 '(0 1 2 3 4 5))
+ ⇒ (9 1 2 3 4 5)
+ (-replace-at 1 9 '(0 1 2 3 4 5))
+ ⇒ (0 9 2 3 4 5)
+ (-replace-at 4 9 '(0 1 2 3 4 5))
+ ⇒ (0 1 2 3 9 5)
+
+ -- Function: -update-at (n func list)
+ Return a list with element at Nth position in LIST replaced with
+ ‘(func (nth n list))‘.
+
+ See also: ‘-map-when’ (*note -map-when::)
+
+ (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5))
+ ⇒ (9 1 2 3 4 5)
+ (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5))
+ ⇒ (0 9 2 3 4 5)
+ (--update-at 2 (length it) '("foo" "bar" "baz" "quux"))
+ ⇒ ("foo" "bar" 3 "quux")
+
+ -- Function: -remove-at (n list)
+ Return a list with element at Nth position in LIST removed.
+
+ See also: ‘-remove-at-indices’ (*note -remove-at-indices::),
+ ‘-remove’ (*note -remove::)
+
+ (-remove-at 0 '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("1" "2" "3" "4" "5")
+ (-remove-at 1 '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("0" "2" "3" "4" "5")
+ (-remove-at 2 '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("0" "1" "3" "4" "5")
+
+ -- Function: -remove-at-indices (indices list)
+ Return a list whose elements are elements from LIST without
+ elements selected as ‘(nth i list)‘ for all i from INDICES.
+
+ See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note
+ -remove::)
+
+ (-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("1" "2" "3" "4" "5")
+ (-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("1" "3" "5")
+ (-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5"))
+ ⇒ ("1" "2" "3" "4")
+
+
+File: dash.info, Node: Reductions, Next: Unfolding, Prev: List to list, Up: Functions
+
+2.4 Reductions
+==============
+
+Functions reducing lists to a single value (which may also be a list).
+
+ -- Function: -reduce-from (fn init list)
+ Reduce the function FN across LIST, starting with INIT. Return the
+ result of applying FN to INIT and the first element of LIST, then
+ applying FN to that result and the second element, etc. If LIST is
+ empty, return INIT without calling FN.
+
+ This function’s anaphoric counterpart is ‘--reduce-from’.
+
+ For other folds, see also ‘-reduce’ (*note -reduce::) and
+ ‘-reduce-r’ (*note -reduce-r::).
+
+ (-reduce-from #'- 10 '(1 2 3))
+ ⇒ 4
+ (-reduce-from #'list 10 '(1 2 3))
+ ⇒ (((10 1) 2) 3)
+ (--reduce-from (concat acc " " it) "START" '("a" "b" "c"))
+ ⇒ "START a b c"
+
+ -- Function: -reduce-r-from (fn init list)
+ Reduce the function FN across LIST in reverse, starting with INIT.
+ Return the result of applying FN to the last element of LIST and
+ INIT, then applying FN to the second-to-last element and the
+ previous result of FN, etc. That is, the first argument of FN is
+ the current element, and its second argument the accumulated value.
+ If LIST is empty, return INIT without calling FN.
+
+ This function is like ‘-reduce-from’ (*note -reduce-from::) but the
+ operation associates from the right rather than left. In other
+ words, it starts from the end of LIST and flips the arguments to
+ FN. Conceptually, it is like replacing the conses in LIST with
+ applications of FN, and its last link with INIT, and evaluating the
+ resulting expression.
+
+ This function’s anaphoric counterpart is ‘--reduce-r-from’.
+
+ For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and
+ ‘-reduce’ (*note -reduce::).
+
+ (-reduce-r-from #'- 10 '(1 2 3))
+ ⇒ -8
+ (-reduce-r-from #'list 10 '(1 2 3))
+ ⇒ (1 (2 (3 10)))
+ (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c"))
+ ⇒ "a b c END"
+
+ -- Function: -reduce (fn list)
+ Reduce the function FN across LIST. Return the result of applying
+ FN to the first two elements of LIST, then applying FN to that
+ result and the third element, etc. If LIST contains a single
+ element, return it without calling FN. If LIST is empty, return
+ the result of calling FN with no arguments.
+
+ This function’s anaphoric counterpart is ‘--reduce’.
+
+ For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and
+ ‘-reduce-r’ (*note -reduce-r::).
+
+ (-reduce #'- '(1 2 3 4))
+ ⇒ -8
+ (-reduce #'list '(1 2 3 4))
+ ⇒ (((1 2) 3) 4)
+ (--reduce (format "%s-%d" acc it) '(1 2 3))
+ ⇒ "1-2-3"
+
+ -- Function: -reduce-r (fn list)
+ Reduce the function FN across LIST in reverse. Return the result
+ of applying FN to the last two elements of LIST, then applying FN
+ to the third-to-last element and the previous result of FN, etc.
+ That is, the first argument of FN is the current element, and its
+ second argument the accumulated value. If LIST contains a single
+ element, return it without calling FN. If LIST is empty, return
+ the result of calling FN with no arguments.
+
+ This function is like ‘-reduce’ (*note -reduce::) but the operation
+ associates from the right rather than left. In other words, it
+ starts from the end of LIST and flips the arguments to FN.
+ Conceptually, it is like replacing the conses in LIST with
+ applications of FN, ignoring its last link, and evaluating the
+ resulting expression.
+
+ This function’s anaphoric counterpart is ‘--reduce-r’.
+
+ For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::)
+ and ‘-reduce’ (*note -reduce::).
+
+ (-reduce-r #'- '(1 2 3 4))
+ ⇒ -2
+ (-reduce-r #'list '(1 2 3 4))
+ ⇒ (1 (2 (3 4)))
+ (--reduce-r (format "%s-%d" acc it) '(1 2 3))
+ ⇒ "3-2-1"
+
+ -- Function: -reductions-from (fn init list)
+ Return a list of FN’s intermediate reductions across LIST. That
+ is, a list of the intermediate values of the accumulator when
+ ‘-reduce-from’ (*note -reduce-from::) (which see) is called with
+ the same arguments.
+
+ This function’s anaphoric counterpart is ‘--reductions-from’.
+
+ For other folds, see also ‘-reductions’ (*note -reductions::) and
+ ‘-reductions-r’ (*note -reductions-r::).
+
+ (-reductions-from #'max 0 '(2 1 4 3))
+ ⇒ (0 2 2 4 4)
+ (-reductions-from #'* 1 '(1 2 3 4))
+ ⇒ (1 1 2 6 24)
+ (--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3))
+ ⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)")
+
+ -- Function: -reductions-r-from (fn init list)
+ Return a list of FN’s intermediate reductions across reversed LIST.
+ That is, a list of the intermediate values of the accumulator when
+ ‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called
+ with the same arguments.
+
+ This function’s anaphoric counterpart is ‘--reductions-r-from’.
+
+ For other folds, see also ‘-reductions’ (*note -reductions::) and
+ ‘-reductions-r’ (*note -reductions-r::).
+
+ (-reductions-r-from #'max 0 '(2 1 4 3))
+ ⇒ (4 4 4 3 0)
+ (-reductions-r-from #'* 1 '(1 2 3 4))
+ ⇒ (24 24 12 4 1)
+ (--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3))
+ ⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT")
+
+ -- Function: -reductions (fn list)
+ Return a list of FN’s intermediate reductions across LIST. That
+ is, a list of the intermediate values of the accumulator when
+ ‘-reduce’ (*note -reduce::) (which see) is called with the same
+ arguments.
+
+ This function’s anaphoric counterpart is ‘--reductions’.
+
+ For other folds, see also ‘-reductions’ (*note -reductions::) and
+ ‘-reductions-r’ (*note -reductions-r::).
+
+ (-reductions #'+ '(1 2 3 4))
+ ⇒ (1 3 6 10)
+ (-reductions #'* '(1 2 3 4))
+ ⇒ (1 2 6 24)
+ (--reductions (format "(FN %s %d)" acc it) '(1 2 3))
+ ⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)")
+
+ -- Function: -reductions-r (fn list)
+ Return a list of FN’s intermediate reductions across reversed LIST.
+ That is, a list of the intermediate values of the accumulator when
+ ‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same
+ arguments.
+
+ This function’s anaphoric counterpart is ‘--reductions-r’.
+
+ For other folds, see also ‘-reductions-r-from’ (*note
+ -reductions-r-from::) and ‘-reductions’ (*note -reductions::).
+
+ (-reductions-r #'+ '(1 2 3 4))
+ ⇒ (10 9 7 4)
+ (-reductions-r #'* '(1 2 3 4))
+ ⇒ (24 24 12 4)
+ (--reductions-r (format "(FN %d %s)" it acc) '(1 2 3))
+ ⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3)
+
+ -- Function: -count (pred list)
+ Counts the number of items in LIST where (PRED item) is non-nil.
+
+ (-count 'even? '(1 2 3 4 5))
+ ⇒ 2
+ (--count (< it 4) '(1 2 3 4))
+ ⇒ 3
+
+ -- Function: -sum (list)
+ Return the sum of LIST.
+
+ (-sum ())
+ ⇒ 0
+ (-sum '(1))
+ ⇒ 1
+ (-sum '(1 2 3 4))
+ ⇒ 10
+
+ -- Function: -running-sum (list)
+ Return a list with running sums of items in LIST. LIST must be
+ non-empty.
+
+ (-running-sum '(1 2 3 4))
+ ⇒ (1 3 6 10)
+ (-running-sum '(1))
+ ⇒ (1)
+ (-running-sum ())
+ error→ Wrong type argument: consp, nil
+
+ -- Function: -product (list)
+ Return the product of LIST.
+
+ (-product ())
+ ⇒ 1
+ (-product '(1))
+ ⇒ 1
+ (-product '(1 2 3 4))
+ ⇒ 24
+
+ -- Function: -running-product (list)
+ Return a list with running products of items in LIST. LIST must be
+ non-empty.
+
+ (-running-product '(1 2 3 4))
+ ⇒ (1 2 6 24)
+ (-running-product '(1))
+ ⇒ (1)
+ (-running-product ())
+ error→ Wrong type argument: consp, nil
+
+ -- Function: -inits (list)
+ Return all prefixes of LIST.
+
+ (-inits '(1 2 3 4))
+ ⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4))
+ (-inits nil)
+ ⇒ (nil)
+ (-inits '(1))
+ ⇒ (nil (1))
+
+ -- Function: -tails (list)
+ Return all suffixes of LIST
+
+ (-tails '(1 2 3 4))
+ ⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil)
+ (-tails nil)
+ ⇒ (nil)
+ (-tails '(1))
+ ⇒ ((1) nil)
+
+ -- Function: -common-prefix (&rest lists)
+ Return the longest common prefix of LISTS.
+
+ (-common-prefix '(1))
+ ⇒ (1)
+ (-common-prefix '(1 2) '(3 4) '(1 2))
+ ⇒ ()
+ (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4))
+ ⇒ (1 2)
+
+ -- Function: -common-suffix (&rest lists)
+ Return the longest common suffix of LISTS.
+
+ (-common-suffix '(1))
+ ⇒ (1)
+ (-common-suffix '(1 2) '(3 4) '(1 2))
+ ⇒ ()
+ (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4))
+ ⇒ (3 4)
+
+ -- Function: -min (list)
+ Return the smallest value from LIST of numbers or markers.
+
+ (-min '(0))
+ ⇒ 0
+ (-min '(3 2 1))
+ ⇒ 1
+ (-min '(1 2 3))
+ ⇒ 1
+
+ -- Function: -min-by (comparator list)
+ Take a comparison function COMPARATOR and a LIST and return the
+ least element of the list by the comparison function.
+
+ See also combinator ‘-on’ (*note -on::) which can transform the
+ values before comparing them.
+
+ (-min-by '> '(4 3 6 1))
+ ⇒ 1
+ (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
+ ⇒ (1 2 3)
+ (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
+ ⇒ (2)
+
+ -- Function: -max (list)
+ Return the largest value from LIST of numbers or markers.
+
+ (-max '(0))
+ ⇒ 0
+ (-max '(3 2 1))
+ ⇒ 3
+ (-max '(1 2 3))
+ ⇒ 3
+
+ -- Function: -max-by (comparator list)
+ Take a comparison function COMPARATOR and a LIST and return the
+ greatest element of the list by the comparison function.
+
+ See also combinator ‘-on’ (*note -on::) which can transform the
+ values before comparing them.
+
+ (-max-by '> '(4 3 6 1))
+ ⇒ 6
+ (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
+ ⇒ (3 2)
+ (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
+ ⇒ (1 2 3)
+
+
+File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Functions
+
+2.5 Unfolding
+=============
+
+Operations dual to reductions, building lists from a seed value rather
+than consuming a list to produce a single value.
+
+ -- Function: -iterate (fun init n)
+ Return a list of iterated applications of FUN to INIT.
+
+ This means a list of the form:
+
+ (INIT (FUN INIT) (FUN (FUN INIT)) ...)
+
+ N is the length of the returned list.
+
+ (-iterate #'1+ 1 10)
+ ⇒ (1 2 3 4 5 6 7 8 9 10)
+ (-iterate (lambda (x) (+ x x)) 2 5)
+ ⇒ (2 4 8 16 32)
+ (--iterate (* it it) 2 5)
+ ⇒ (2 4 16 256 65536)
+
+ -- Function: -unfold (fun seed)
+ Build a list from SEED using FUN.
+
+ This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while
+ -reduce-r consumes a list to produce a single value, ‘-unfold’
+ (*note -unfold::) takes a seed value and builds a (potentially
+ infinite!) list.
+
+ FUN should return ‘nil’ to stop the generating process, or a cons
+ (A . B), where A will be prepended to the result and B is the new
+ seed.
+
+ (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10)
+ ⇒ (10 9 8 7 6 5 4 3 2 1)
+ (--unfold (when it (cons it (cdr it))) '(1 2 3 4))
+ ⇒ ((1 2 3 4) (2 3 4) (3 4) (4))
+ (--unfold (when it (cons it (butlast it))) '(1 2 3 4))
+ ⇒ ((1 2 3 4) (1 2 3) (1 2) (1))
+
+
+File: dash.info, Node: Predicates, Next: Partitioning, Prev: Unfolding, Up: Functions
+
+2.6 Predicates
+==============
+
+Reductions of one or more lists to a boolean value.
+
+ -- Function: -some (pred list)
+ Return (PRED x) for the first LIST item where (PRED x) is non-nil,
+ else nil.
+
+ Alias: ‘-any’.
+
+ This function’s anaphoric counterpart is ‘--some’.
+
+ (-some #'stringp '(1 "2" 3))
+ ⇒ t
+ (--some (string-match-p "x" it) '("foo" "axe" "xor"))
+ ⇒ 1
+ (--some (= it-index 3) '(0 1 2))
+ ⇒ nil
+
+ -- Function: -every (pred list)
+ Return non-nil if PRED returns non-nil for all items in LIST. If
+ so, return the last such result of PRED. Otherwise, once an item
+ is reached for which PRED returns nil, return nil without calling
+ PRED on any further LIST elements.
+
+ This function is like ‘-every-p’, but on success returns the last
+ non-nil result of PRED instead of just t.
+
+ This function’s anaphoric counterpart is ‘--every’.
+
+ (-every #'numberp '(1 2 3))
+ ⇒ t
+ (--every (string-match-p "x" it) '("axe" "xor"))
+ ⇒ 0
+ (--every (= it it-index) '(0 1 3))
+ ⇒ nil
+
+ -- Function: -any? (pred list)
+ Return t if (PRED x) is non-nil for any x in LIST, else nil.
+
+ Alias: ‘-any-p’, ‘-some?’, ‘-some-p’
+
+ (-any? #'numberp '(nil 0 t))
+ ⇒ t
+ (-any? #'numberp '(nil t t))
+ ⇒ nil
+ (-any? #'null '(1 3 5))
+ ⇒ nil
+
+ -- Function: -all? (pred list)
+ Return t if (PRED X) is non-nil for all X in LIST, else nil. In
+ the latter case, stop after the first X for which (PRED X) is nil,
+ without calling PRED on any subsequent elements of LIST.
+
+ The similar function ‘-every’ (*note -every::) is more widely
+ useful, since it returns the last non-nil result of PRED instead of
+ just t on success.
+
+ Alias: ‘-all-p’, ‘-every-p’, ‘-every?’.
+
+ This function’s anaphoric counterpart is ‘--all?’.
+
+ (-all? #'numberp '(1 2 3))
+ ⇒ t
+ (-all? #'numberp '(2 t 6))
+ ⇒ nil
+ (--all? (= 0 (% it 2)) '(2 4 6))
+ ⇒ t
+
+ -- Function: -none? (pred list)
+ Return t if (PRED x) is nil for all x in LIST, else nil.
+
+ Alias: ‘-none-p’
+
+ (-none? 'even? '(1 2 3))
+ ⇒ nil
+ (-none? 'even? '(1 3 5))
+ ⇒ t
+ (--none? (= 0 (% it 2)) '(1 2 3))
+ ⇒ nil
+
+ -- Function: -only-some? (pred list)
+ Return ‘t‘ if at least one item of LIST matches PRED and at least
+ one item of LIST does not match PRED. Return ‘nil‘ both if all
+ items match the predicate or if none of the items match the
+ predicate.
+
+ Alias: ‘-only-some-p’
+
+ (-only-some? 'even? '(1 2 3))
+ ⇒ t
+ (-only-some? 'even? '(1 3 5))
+ ⇒ nil
+ (-only-some? 'even? '(2 4 6))
+ ⇒ nil
+
+ -- Function: -contains? (list element)
+ Return non-nil if LIST contains ELEMENT.
+
+ The test for equality is done with ‘equal’, or with ‘-compare-fn’
+ if that’s non-nil.
+
+ Alias: ‘-contains-p’
+
+ (-contains? '(1 2 3) 1)
+ ⇒ t
+ (-contains? '(1 2 3) 2)
+ ⇒ t
+ (-contains? '(1 2 3) 4)
+ ⇒ nil
+
+ -- Function: -same-items? (list list2)
+ Return true if LIST and LIST2 has the same items.
+
+ The order of the elements in the lists does not matter.
+
+ Alias: ‘-same-items-p’
+
+ (-same-items? '(1 2 3) '(1 2 3))
+ ⇒ t
+ (-same-items? '(1 2 3) '(3 2 1))
+ ⇒ t
+ (-same-items? '(1 2 3) '(1 2 3 4))
+ ⇒ nil
+
+ -- Function: -is-prefix? (prefix list)
+ Return non-nil if PREFIX is a prefix of LIST.
+
+ Alias: ‘-is-prefix-p’.
+
+ (-is-prefix? '(1 2 3) '(1 2 3 4 5))
+ ⇒ t
+ (-is-prefix? '(1 2 3 4 5) '(1 2 3))
+ ⇒ nil
+ (-is-prefix? '(1 3) '(1 2 3 4 5))
+ ⇒ nil
+
+ -- Function: -is-suffix? (suffix list)
+ Return non-nil if SUFFIX is a suffix of LIST.
+
+ Alias: ‘-is-suffix-p’.
+
+ (-is-suffix? '(3 4 5) '(1 2 3 4 5))
+ ⇒ t
+ (-is-suffix? '(1 2 3 4 5) '(3 4 5))
+ ⇒ nil
+ (-is-suffix? '(3 5) '(1 2 3 4 5))
+ ⇒ nil
+
+ -- Function: -is-infix? (infix list)
+ Return non-nil if INFIX is infix of LIST.
+
+ This operation runs in O(n^2) time
+
+ Alias: ‘-is-infix-p’
+
+ (-is-infix? '(1 2 3) '(1 2 3 4 5))
+ ⇒ t
+ (-is-infix? '(2 3 4) '(1 2 3 4 5))
+ ⇒ t
+ (-is-infix? '(3 4 5) '(1 2 3 4 5))
+ ⇒ t
+
+ -- Function: -cons-pair? (obj)
+ Return non-nil if OBJ is a true cons pair. That is, a cons (A .
+ B) where B is not a list.
+
+ Alias: ‘-cons-pair-p’.
+
+ (-cons-pair? '(1 . 2))
+ ⇒ t
+ (-cons-pair? '(1 2))
+ ⇒ nil
+ (-cons-pair? '(1))
+ ⇒ nil
+
+
+File: dash.info, Node: Partitioning, Next: Indexing, Prev: Predicates, Up: Functions
+
+2.7 Partitioning
+================
+
+Functions partitioning the input list into a list of lists.
+
+ -- Function: -split-at (n list)
+ Split LIST into two sublists after the Nth element. The result is
+ a list of two elements (TAKE DROP) where TAKE is a new list of the
+ first N elements of LIST, and DROP is the remaining elements of
+ LIST (not a copy). TAKE and DROP are like the results of ‘-take’
+ (*note -take::) and ‘-drop’ (*note -drop::), respectively, but the
+ split is done in a single list traversal.
+
+ (-split-at 3 '(1 2 3 4 5))
+ ⇒ ((1 2 3) (4 5))
+ (-split-at 17 '(1 2 3 4 5))
+ ⇒ ((1 2 3 4 5) nil)
+ (-split-at 0 '(1 2 3 4 5))
+ ⇒ (nil (1 2 3 4 5))
+
+ -- Function: -split-with (pred list)
+ Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)),
+ in no more than one pass through the list.
+
+ (-split-with 'even? '(1 2 3 4))
+ ⇒ (nil (1 2 3 4))
+ (-split-with 'even? '(2 4 5 6))
+ ⇒ ((2 4) (5 6))
+ (--split-with (< it 4) '(1 2 3 4 3 2 1))
+ ⇒ ((1 2 3) (4 3 2 1))
+
+ -- Macro: -split-on (item list)
+ Split the LIST each time ITEM is found.
+
+ Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is
+ discarded from the results. Empty lists are also removed from the
+ result.
+
+ Comparison is done by ‘equal’.
+
+ See also ‘-split-when’ (*note -split-when::)
+
+ (-split-on '| '(Nil | Leaf a | Node [Tree a]))
+ ⇒ ((Nil) (Leaf a) (Node [Tree a]))
+ (-split-on :endgroup '("a" "b" :endgroup "c" :endgroup "d" "e"))
+ ⇒ (("a" "b") ("c") ("d" "e"))
+ (-split-on :endgroup '("a" "b" :endgroup :endgroup "d" "e"))
+ ⇒ (("a" "b") ("d" "e"))
+
+ -- Function: -split-when (fn list)
+ Split the LIST on each element where FN returns non-nil.
+
+ Unlike ‘-partition-by’ (*note -partition-by::), the "matched"
+ element is discarded from the results. Empty lists are also
+ removed from the result.
+
+ This function can be thought of as a generalization of
+ ‘split-string’.
+
+ (-split-when 'even? '(1 2 3 4 5 6))
+ ⇒ ((1) (3) (5))
+ (-split-when 'even? '(1 2 3 4 6 8 9))
+ ⇒ ((1) (3) (9))
+ (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args))
+ ⇒ ((a b) (c d) (args))
+
+ -- Function: -separate (pred list)
+ Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one
+ pass through the list.
+
+ (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7))
+ ⇒ ((2 4 6) (1 3 5 7))
+ (--separate (< it 5) '(3 7 5 9 3 2 1 4 6))
+ ⇒ ((3 3 2 1 4) (7 5 9 6))
+ (-separate 'cdr '((1 2) (1) (1 2 3) (4)))
+ ⇒ (((1 2) (1 2 3)) ((1) (4)))
+
+ -- Function: -partition (n list)
+ Return a new list with the items in LIST grouped into N-sized
+ sublists. If there are not enough items to make the last group
+ N-sized, those items are discarded.
+
+ (-partition 2 '(1 2 3 4 5 6))
+ ⇒ ((1 2) (3 4) (5 6))
+ (-partition 2 '(1 2 3 4 5 6 7))
+ ⇒ ((1 2) (3 4) (5 6))
+ (-partition 3 '(1 2 3 4 5 6 7))
+ ⇒ ((1 2 3) (4 5 6))
+
+ -- Function: -partition-all (n list)
+ Return a new list with the items in LIST grouped into N-sized
+ sublists. The last group may contain less than N items.
+
+ (-partition-all 2 '(1 2 3 4 5 6))
+ ⇒ ((1 2) (3 4) (5 6))
+ (-partition-all 2 '(1 2 3 4 5 6 7))
+ ⇒ ((1 2) (3 4) (5 6) (7))
+ (-partition-all 3 '(1 2 3 4 5 6 7))
+ ⇒ ((1 2 3) (4 5 6) (7))
+
+ -- Function: -partition-in-steps (n step list)
+ Return a new list with the items in LIST grouped into N-sized
+ sublists at offsets STEP apart. If there are not enough items to
+ make the last group N-sized, those items are discarded.
+
+ (-partition-in-steps 2 1 '(1 2 3 4))
+ ⇒ ((1 2) (2 3) (3 4))
+ (-partition-in-steps 3 2 '(1 2 3 4))
+ ⇒ ((1 2 3))
+ (-partition-in-steps 3 2 '(1 2 3 4 5))
+ ⇒ ((1 2 3) (3 4 5))
+
+ -- Function: -partition-all-in-steps (n step list)
+ Return a new list with the items in LIST grouped into N-sized
+ sublists at offsets STEP apart. The last groups may contain less
+ than N items.
+
+ (-partition-all-in-steps 2 1 '(1 2 3 4))
+ ⇒ ((1 2) (2 3) (3 4) (4))
+ (-partition-all-in-steps 3 2 '(1 2 3 4))
+ ⇒ ((1 2 3) (3 4))
+ (-partition-all-in-steps 3 2 '(1 2 3 4 5))
+ ⇒ ((1 2 3) (3 4 5) (5))
+
+ -- Function: -partition-by (fn list)
+ Apply FN to each item in LIST, splitting it each time FN returns a
+ new value.
+
+ (-partition-by 'even? ())
+ ⇒ ()
+ (-partition-by 'even? '(1 1 2 2 2 3 4 6 8))
+ ⇒ ((1 1) (2 2 2) (3) (4 6 8))
+ (--partition-by (< it 3) '(1 2 3 4 3 2 1))
+ ⇒ ((1 2) (3 4 3) (2 1))
+
+ -- Function: -partition-by-header (fn list)
+ Apply FN to the first item in LIST. That is the header value.
+ Apply FN to each item in LIST, splitting it each time FN returns
+ the header value, but only after seeing at least one other value
+ (the body).
+
+ (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4))
+ ⇒ ((1 2 3) (1 2) (1 2 3 4))
+ (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0))
+ ⇒ ((1 2 0) (1 0) (1 2 3 0))
+ (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1))
+ ⇒ ((2 1 1 1) (4 1 3 5) (6 6 1))
+
+ -- Function: -partition-after-pred (pred list)
+ Partition LIST after each element for which PRED returns non-nil.
+
+ This function’s anaphoric counterpart is ‘--partition-after-pred’.
+
+ (-partition-after-pred #'booleanp ())
+ ⇒ ()
+ (-partition-after-pred #'booleanp '(t t))
+ ⇒ ((t) (t))
+ (-partition-after-pred #'booleanp '(0 0 t t 0 t))
+ ⇒ ((0 0 t) (t) (0 t))
+
+ -- Function: -partition-before-pred (pred list)
+ Partition directly before each time PRED is true on an element of
+ LIST.
+
+ (-partition-before-pred #'booleanp ())
+ ⇒ ()
+ (-partition-before-pred #'booleanp '(0 t))
+ ⇒ ((0) (t))
+ (-partition-before-pred #'booleanp '(0 0 t 0 t t))
+ ⇒ ((0 0) (t 0) (t) (t))
+
+ -- Function: -partition-before-item (item list)
+ Partition directly before each time ITEM appears in LIST.
+
+ (-partition-before-item 3 ())
+ ⇒ ()
+ (-partition-before-item 3 '(1))
+ ⇒ ((1))
+ (-partition-before-item 3 '(3))
+ ⇒ ((3))
+
+ -- Function: -partition-after-item (item list)
+ Partition directly after each time ITEM appears in LIST.
+
+ (-partition-after-item 3 ())
+ ⇒ ()
+ (-partition-after-item 3 '(1))
+ ⇒ ((1))
+ (-partition-after-item 3 '(3))
+ ⇒ ((3))
+
+ -- Function: -group-by (fn list)
+ Separate LIST into an alist whose keys are FN applied to the
+ elements of LIST. Keys are compared by ‘equal’.
+
+ (-group-by 'even? ())
+ ⇒ ()
+ (-group-by 'even? '(1 1 2 2 2 3 4 6 8))
+ ⇒ ((nil 1 1 3) (t 2 2 2 4 6 8))
+ (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e"))
+ ⇒ (("a" "a/b" "a/e") ("c" "c/d"))
+
+
+File: dash.info, Node: Indexing, Next: Set operations, Prev: Partitioning, Up: Functions
+
+2.8 Indexing
+============
+
+Functions retrieving or sorting based on list indices and related
+predicates.
+
+ -- Function: -elem-index (elem list)
+ Return the index of the first element in the given LIST which is
+ equal to the query element ELEM, or nil if there is no such
+ element.
+
+ (-elem-index 2 '(6 7 8 2 3 4))
+ ⇒ 3
+ (-elem-index "bar" '("foo" "bar" "baz"))
+ ⇒ 1
+ (-elem-index '(1 2) '((3) (5 6) (1 2) nil))
+ ⇒ 2
+
+ -- Function: -elem-indices (elem list)
+ Return the indices of all elements in LIST equal to the query
+ element ELEM, in ascending order.
+
+ (-elem-indices 2 '(6 7 8 2 3 4 2 1))
+ ⇒ (3 6)
+ (-elem-indices "bar" '("foo" "bar" "baz"))
+ ⇒ (1)
+ (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil))
+ ⇒ (1 3)
+
+ -- Function: -find-index (pred list)
+ Take a predicate PRED and a LIST and return the index of the first
+ element in the list satisfying the predicate, or nil if there is no
+ such element.
+
+ See also ‘-first’ (*note -first::).
+
+ (-find-index 'even? '(2 4 1 6 3 3 5 8))
+ ⇒ 0
+ (--find-index (< 5 it) '(2 4 1 6 3 3 5 8))
+ ⇒ 3
+ (-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz"))
+ ⇒ 1
+
+ -- Function: -find-last-index (pred list)
+ Take a predicate PRED and a LIST and return the index of the last
+ element in the list satisfying the predicate, or nil if there is no
+ such element.
+
+ See also ‘-last’ (*note -last::).
+
+ (-find-last-index 'even? '(2 4 1 6 3 3 5 8))
+ ⇒ 7
+ (--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2))
+ ⇒ 5
+ (-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz"))
+ ⇒ 1
+
+ -- Function: -find-indices (pred list)
+ Return the indices of all elements in LIST satisfying the predicate
+ PRED, in ascending order.
+
+ (-find-indices 'even? '(2 4 1 6 3 3 5 8))
+ ⇒ (0 1 3 7)
+ (--find-indices (< 5 it) '(2 4 1 6 3 3 5 8))
+ ⇒ (3 7)
+ (-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz"))
+ ⇒ (1)
+
+ -- Function: -grade-up (comparator list)
+ Grade elements of LIST using COMPARATOR relation. This yields a
+ permutation vector such that applying this permutation to LIST
+ sorts it in ascending order.
+
+ (-grade-up #'< '(3 1 4 2 1 3 3))
+ ⇒ (1 4 3 0 5 6 2)
+ (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l))
+ ⇒ (1 1 2 3 3 3 4)
+
+ -- Function: -grade-down (comparator list)
+ Grade elements of LIST using COMPARATOR relation. This yields a
+ permutation vector such that applying this permutation to LIST
+ sorts it in descending order.
+
+ (-grade-down #'< '(3 1 4 2 1 3 3))
+ ⇒ (2 0 5 6 3 1 4)
+ (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l))
+ ⇒ (4 3 3 3 2 1 1)
+
+
+File: dash.info, Node: Set operations, Next: Other list operations, Prev: Indexing, Up: Functions
+
+2.9 Set operations
+==================
+
+Operations pretending lists are sets.
+
+ -- Function: -union (list list2)
+ Return a new list containing the elements of LIST and elements of
+ LIST2 that are not in LIST. The test for equality is done with
+ ‘equal’, or with ‘-compare-fn’ if that’s non-nil.
+
+ (-union '(1 2 3) '(3 4 5))
+ ⇒ (1 2 3 4 5)
+ (-union '(1 2 3 4) ())
+ ⇒ (1 2 3 4)
+ (-union '(1 1 2 2) '(3 2 1))
+ ⇒ (1 1 2 2 3)
+
+ -- Function: -difference (list list2)
+ Return a new list with only the members of LIST that are not in
+ LIST2. The test for equality is done with ‘equal’, or with
+ ‘-compare-fn’ if that’s non-nil.
+
+ (-difference () ())
+ ⇒ ()
+ (-difference '(1 2 3) '(4 5 6))
+ ⇒ (1 2 3)
+ (-difference '(1 2 3 4) '(3 4 5 6))
+ ⇒ (1 2)
+
+ -- Function: -intersection (list list2)
+ Return a new list containing only the elements that are members of
+ both LIST and LIST2. The test for equality is done with ‘equal’,
+ or with ‘-compare-fn’ if that’s non-nil.
+
+ (-intersection () ())
+ ⇒ ()
+ (-intersection '(1 2 3) '(4 5 6))
+ ⇒ ()
+ (-intersection '(1 2 3 4) '(3 4 5 6))
+ ⇒ (3 4)
+
+ -- Function: -powerset (list)
+ Return the power set of LIST.
+
+ (-powerset ())
+ ⇒ (nil)
+ (-powerset '(x y z))
+ ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil)
+
+ -- Function: -permutations (list)
+ Return the permutations of LIST.
+
+ (-permutations ())
+ ⇒ (nil)
+ (-permutations '(1 2))
+ ⇒ ((1 2) (2 1))
+ (-permutations '(a b c))
+ ⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))
+
+ -- Function: -distinct (list)
+ Return a new list with all duplicates removed. The test for
+ equality is done with ‘equal’, or with ‘-compare-fn’ if that’s
+ non-nil.
+
+ Alias: ‘-uniq’
+
+ (-distinct ())
+ ⇒ ()
+ (-distinct '(1 2 2 4))
+ ⇒ (1 2 4)
+ (-distinct '(t t t))
+ ⇒ (t)
+
+
+File: dash.info, Node: Other list operations, Next: Tree operations, Prev: Set operations, Up: Functions
+
+2.10 Other list operations
+==========================
+
+Other list functions not fit to be classified elsewhere.
+
+ -- Function: -rotate (n list)
+ Rotate LIST N places to the right (left if N is negative). The
+ time complexity is O(n).
+
+ (-rotate 3 '(1 2 3 4 5 6 7))
+ ⇒ (5 6 7 1 2 3 4)
+ (-rotate -3 '(1 2 3 4 5 6 7))
+ ⇒ (4 5 6 7 1 2 3)
+ (-rotate 16 '(1 2 3 4 5 6 7))
+ ⇒ (6 7 1 2 3 4 5)
+
+ -- Function: -repeat (n x)
+ Return a new list of length N with each element being X. Return
+ nil if N is less than 1.
+
+ (-repeat 3 :a)
+ ⇒ (:a :a :a)
+ (-repeat 1 :a)
+ ⇒ (:a)
+ (-repeat 0 :a)
+ ⇒ nil
+
+ -- Function: -cons* (&rest args)
+ Make a new list from the elements of ARGS. The last 2 elements of
+ ARGS are used as the final cons of the result, so if the final
+ element of ARGS is not a list, the result is a dotted list. With
+ no ARGS, return nil.
+
+ (-cons* 1 2)
+ ⇒ (1 . 2)
+ (-cons* 1 2 3)
+ ⇒ (1 2 . 3)
+ (-cons* 1)
+ ⇒ 1
+
+ -- Function: -snoc (list elem &rest elements)
+ Append ELEM to the end of the list.
+
+ This is like ‘cons’, but operates on the end of list.
+
+ If ELEMENTS is non nil, append these to the list as well.
+
+ (-snoc '(1 2 3) 4)
+ ⇒ (1 2 3 4)
+ (-snoc '(1 2 3) 4 5 6)
+ ⇒ (1 2 3 4 5 6)
+ (-snoc '(1 2 3) '(4 5 6))
+ ⇒ (1 2 3 (4 5 6))
+
+ -- Function: -interpose (sep list)
+ Return a new list of all elements in LIST separated by SEP.
+
+ (-interpose "-" ())
+ ⇒ ()
+ (-interpose "-" '("a"))
+ ⇒ ("a")
+ (-interpose "-" '("a" "b" "c"))
+ ⇒ ("a" "-" "b" "-" "c")
+
+ -- Function: -interleave (&rest lists)
+ Return a new list of the first item in each list, then the second
+ etc.
+
+ (-interleave '(1 2) '("a" "b"))
+ ⇒ (1 "a" 2 "b")
+ (-interleave '(1 2) '("a" "b") '("A" "B"))
+ ⇒ (1 "a" "A" 2 "b" "B")
+ (-interleave '(1 2 3) '("a" "b"))
+ ⇒ (1 "a" 2 "b")
+
+ -- Function: -iota (count &optional start step)
+ Return a list containing COUNT numbers. Starts from START and adds
+ STEP each time. The default START is zero, the default STEP is 1.
+ This function takes its name from the corresponding primitive in
+ the APL language.
+
+ (-iota 6)
+ ⇒ (0 1 2 3 4 5)
+ (-iota 4 2.5 -2)
+ ⇒ (2.5 0.5 -1.5 -3.5)
+ (-iota -1)
+ error→ Wrong type argument: natnump, -1
+
+ -- Function: -zip-with (fn list1 list2)
+ Zip the two lists LIST1 and LIST2 using a function FN. This
+ function is applied pairwise taking as first argument element of
+ LIST1 and as second argument element of LIST2 at corresponding
+ position.
+
+ The anaphoric form ‘--zip-with’ binds the elements from LIST1 as
+ symbol ‘it’, and the elements from LIST2 as symbol ‘other’.
+
+ (-zip-with '+ '(1 2 3) '(4 5 6))
+ ⇒ (5 7 9)
+ (-zip-with 'cons '(1 2 3) '(4 5 6))
+ ⇒ ((1 . 4) (2 . 5) (3 . 6))
+ (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde"))
+ ⇒ ("Batman and Robin" "Jekyll and Hyde")
+
+ -- Function: -zip (&rest lists)
+ Zip LISTS together. Group the head of each list, followed by the
+ second elements of each list, and so on. The lengths of the
+ returned groupings are equal to the length of the shortest input
+ list.
+
+ If two lists are provided as arguments, return the groupings as a
+ list of cons cells. Otherwise, return the groupings as a list of
+ lists.
+
+ Use ‘-zip-lists’ (*note -zip-lists::) if you need the return value
+ to always be a list of lists.
+
+ Alias: ‘-zip-pair’
+
+ See also: ‘-zip-lists’ (*note -zip-lists::)
+
+ (-zip '(1 2 3) '(4 5 6))
+ ⇒ ((1 . 4) (2 . 5) (3 . 6))
+ (-zip '(1 2 3) '(4 5 6 7))
+ ⇒ ((1 . 4) (2 . 5) (3 . 6))
+ (-zip '(1 2) '(3 4 5) '(6))
+ ⇒ ((1 3 6))
+
+ -- Function: -zip-lists (&rest lists)
+ Zip LISTS together. Group the head of each list, followed by the
+ second elements of each list, and so on. The lengths of the
+ returned groupings are equal to the length of the shortest input
+ list.
+
+ The return value is always list of lists, which is a difference
+ from ‘-zip-pair’ which returns a cons-cell in case two input lists
+ are provided.
+
+ See also: ‘-zip’ (*note -zip::)
+
+ (-zip-lists '(1 2 3) '(4 5 6))
+ ⇒ ((1 4) (2 5) (3 6))
+ (-zip-lists '(1 2 3) '(4 5 6 7))
+ ⇒ ((1 4) (2 5) (3 6))
+ (-zip-lists '(1 2) '(3 4 5) '(6))
+ ⇒ ((1 3 6))
+
+ -- Function: -zip-fill (fill-value &rest lists)
+ Zip LISTS, with FILL-VALUE padded onto the shorter lists. The
+ lengths of the returned groupings are equal to the length of the
+ longest input list.
+
+ (-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9))
+ ⇒ ((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0))
+
+ -- Function: -unzip (lists)
+ Unzip LISTS.
+
+ This works just like ‘-zip’ (*note -zip::) but takes a list of
+ lists instead of a variable number of arguments, such that
+
+ (-unzip (-zip L1 L2 L3 ...))
+
+ is identity (given that the lists are the same length).
+
+ Note in particular that calling this on a list of two lists will
+ return a list of cons-cells such that the above identity works.
+
+ See also: ‘-zip’ (*note -zip::)
+
+ (-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g")))
+ ⇒ ((1 2 3) (a b c) ("e" "f" "g"))
+ (-unzip '((1 2) (3 4) (5 6) (7 8) (9 10)))
+ ⇒ ((1 3 5 7 9) (2 4 6 8 10))
+ (-unzip '((1 2) (3 4)))
+ ⇒ ((1 . 3) (2 . 4))
+
+ -- Function: -cycle (list)
+ Return an infinite circular copy of LIST. The returned list cycles
+ through the elements of LIST and repeats from the beginning.
+
+ (-take 5 (-cycle '(1 2 3)))
+ ⇒ (1 2 3 1 2)
+ (-take 7 (-cycle '(1 "and" 3)))
+ ⇒ (1 "and" 3 1 "and" 3 1)
+ (-zip (-cycle '(1 2 3)) '(1 2))
+ ⇒ ((1 . 1) (2 . 2))
+
+ -- Function: -pad (fill-value &rest lists)
+ Appends FILL-VALUE to the end of each list in LISTS such that they
+ will all have the same length.
+
+ (-pad 0 ())
+ ⇒ (nil)
+ (-pad 0 '(1))
+ ⇒ ((1))
+ (-pad 0 '(1 2 3) '(4 5))
+ ⇒ ((1 2 3) (4 5 0))
+
+ -- Function: -table (fn &rest lists)
+ Compute outer product of LISTS using function FN.
+
+ The function FN should have the same arity as the number of
+ supplied lists.
+
+ The outer product is computed by applying fn to all possible
+ combinations created by taking one element from each list in order.
+ The dimension of the result is (length lists).
+
+ See also: ‘-table-flat’ (*note -table-flat::)
+
+ (-table '* '(1 2 3) '(1 2 3))
+ ⇒ ((1 2 3) (2 4 6) (3 6 9))
+ (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4)))
+ ⇒ ((7 15) (10 22))
+ (apply '-table 'list (-repeat 3 '(1 2)))
+ ⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2))))
+
+ -- Function: -table-flat (fn &rest lists)
+ Compute flat outer product of LISTS using function FN.
+
+ The function FN should have the same arity as the number of
+ supplied lists.
+
+ The outer product is computed by applying fn to all possible
+ combinations created by taking one element from each list in order.
+ The results are flattened, ignoring the tensor structure of the
+ result. This is equivalent to calling:
+
+ (-flatten-n (1- (length lists)) (apply ’-table fn lists))
+
+ but the implementation here is much more efficient.
+
+ See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note
+ -table::)
+
+ (-table-flat 'list '(1 2 3) '(a b c))
+ ⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c))
+ (-table-flat '* '(1 2 3) '(1 2 3))
+ ⇒ (1 2 3 2 4 6 3 6 9)
+ (apply '-table-flat 'list (-repeat 3 '(1 2)))
+ ⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2))
+
+ -- Function: -first (pred list)
+ Return the first item in LIST for which PRED returns non-nil.
+ Return nil if no such element is found. To get the first item in
+ the list no questions asked, use ‘car’.
+
+ Alias: ‘-find’.
+
+ This function’s anaphoric counterpart is ‘--first’.
+
+ (-first #'natnump '(-1 0 1))
+ ⇒ 0
+ (-first #'null '(1 2 3))
+ ⇒ nil
+ (--first (> it 2) '(1 2 3))
+ ⇒ 3
+
+ -- Function: -last (pred list)
+ Return the last x in LIST where (PRED x) is non-nil, else nil.
+
+ (-last 'even? '(1 2 3 4 5 6 3 3 3))
+ ⇒ 6
+ (-last 'even? '(1 3 7 5 9))
+ ⇒ nil
+ (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one"))
+ ⇒ "short"
+
+ -- Function: -first-item (list)
+ Return the first item of LIST, or nil on an empty list.
+
+ See also: ‘-second-item’ (*note -second-item::), ‘-last-item’
+ (*note -last-item::).
+
+ (-first-item '(1 2 3))
+ ⇒ 1
+ (-first-item nil)
+ ⇒ nil
+ (let ((list (list 1 2 3))) (setf (-first-item list) 5) list)
+ ⇒ (5 2 3)
+
+ -- Function: -second-item (list)
+ Return the second item of LIST, or nil if LIST is too short.
+
+ See also: ‘-third-item’ (*note -third-item::).
+
+ (-second-item '(1 2 3))
+ ⇒ 2
+ (-second-item nil)
+ ⇒ nil
+
+ -- Function: -third-item (list)
+ Return the third item of LIST, or nil if LIST is too short.
+
+ See also: ‘-fourth-item’ (*note -fourth-item::).
+
+ (-third-item '(1 2 3))
+ ⇒ 3
+ (-third-item nil)
+ ⇒ nil
+
+ -- Function: -fourth-item (list)
+ Return the fourth item of LIST, or nil if LIST is too short.
+
+ See also: ‘-fifth-item’ (*note -fifth-item::).
+
+ (-fourth-item '(1 2 3 4))
+ ⇒ 4
+ (-fourth-item nil)
+ ⇒ nil
+
+ -- Function: -fifth-item (list)
+ Return the fifth item of LIST, or nil if LIST is too short.
+
+ See also: ‘-last-item’ (*note -last-item::).
+
+ (-fifth-item '(1 2 3 4 5))
+ ⇒ 5
+ (-fifth-item nil)
+ ⇒ nil
+
+ -- Function: -last-item (list)
+ Return the last item of LIST, or nil on an empty list.
+
+ (-last-item '(1 2 3))
+ ⇒ 3
+ (-last-item nil)
+ ⇒ nil
+ (let ((list (list 1 2 3))) (setf (-last-item list) 5) list)
+ ⇒ (1 2 5)
+
+ -- Function: -butlast (list)
+ Return a list of all items in list except for the last.
+
+ (-butlast '(1 2 3))
+ ⇒ (1 2)
+ (-butlast '(1 2))
+ ⇒ (1)
+ (-butlast '(1))
+ ⇒ nil
+
+ -- Function: -sort (comparator list)
+ Sort LIST, stably, comparing elements using COMPARATOR. Return the
+ sorted list. LIST is NOT modified by side effects. COMPARATOR is
+ called with two elements of LIST, and should return non-nil if the
+ first element should sort before the second.
+
+ (-sort '< '(3 1 2))
+ ⇒ (1 2 3)
+ (-sort '> '(3 1 2))
+ ⇒ (3 2 1)
+ (--sort (< it other) '(3 1 2))
+ ⇒ (1 2 3)
+
+ -- Function: -list (arg)
+ Ensure ARG is a list. If ARG is already a list, return it as is
+ (not a copy). Otherwise, return a new list with ARG as its only
+ element.
+
+ Another supported calling convention is (-list &rest ARGS). In
+ this case, if ARG is not a list, a new list with all of ARGS as
+ elements is returned. This use is supported for backward
+ compatibility and is otherwise deprecated.
+
+ (-list 1)
+ ⇒ (1)
+ (-list ())
+ ⇒ ()
+ (-list '(1 2 3))
+ ⇒ (1 2 3)
+
+ -- Function: -fix (fn list)
+ Compute the (least) fixpoint of FN with initial input LIST.
+
+ FN is called at least once, results are compared with ‘equal’.
+
+ (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3)))
+ ⇒ ((1) (2) (3))
+ (let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book)))
+ ⇒ (jedi starwars warrior scifi book)
+
+
+File: dash.info, Node: Tree operations, Next: Threading macros, Prev: Other list operations, Up: Functions
+
+2.11 Tree operations
+====================
+
+Functions pretending lists are trees.
+
+ -- Function: -tree-seq (branch children tree)
+ Return a sequence of the nodes in TREE, in depth-first search
+ order.
+
+ BRANCH is a predicate of one argument that returns non-nil if the
+ passed argument is a branch, that is, a node that can have
+ children.
+
+ CHILDREN is a function of one argument that returns the children of
+ the passed branch node.
+
+ Non-branch nodes are simply copied.
+
+ (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7))))
+ ⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7)
+ (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7))))
+ ⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1)
+ (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]])
+ ⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7)
+
+ -- Function: -tree-map (fn tree)
+ Apply FN to each element of TREE while preserving the tree
+ structure.
+
+ (-tree-map '1+ '(1 (2 3) (4 (5 6) 7)))
+ ⇒ (2 (3 4) (5 (6 7) 8))
+ (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4))
+ ⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16))
+ (--tree-map (length it) '("<body>" ("<p>" "text" "</p>") "</body>"))
+ ⇒ (6 (3 4 4) 7)
+
+ -- Function: -tree-map-nodes (pred fun tree)
+ Call FUN on each node of TREE that satisfies PRED.
+
+ If PRED returns nil, continue descending down this node. If PRED
+ returns non-nil, apply FUN to this node and do not descend further.
+
+ (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8)))
+ ⇒ (1 5 4 (5 13 8))
+ (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8)))
+ ⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8))
+ (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d))))
+ ⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode)))
+
+ -- Function: -tree-reduce (fn tree)
+ Use FN to reduce elements of list TREE. If elements of TREE are
+ lists themselves, apply the reduction recursively.
+
+ FN is first applied to first element of the list and second
+ element, then on this result and third element from the list etc.
+
+ See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of
+ zero or one element handled.
+
+ (-tree-reduce '+ '(1 (2 3) (4 5)))
+ ⇒ 15
+ (-tree-reduce 'concat '("strings" (" on" " various") ((" levels"))))
+ ⇒ "strings on various levels"
+ (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "</" sn ">")))) '(body (p "some words") (div "more" (b "bold") "words")))
+ ⇒ "<body><p>some words</p> <div>more <b>bold</b> words</div></body>"
+
+ -- Function: -tree-reduce-from (fn init-value tree)
+ Use FN to reduce elements of list TREE. If elements of TREE are
+ lists themselves, apply the reduction recursively.
+
+ FN is first applied to INIT-VALUE and first element of the list,
+ then on this result and second element from the list etc.
+
+ The initial value is ignored on cons pairs as they always contain
+ two elements.
+
+ (-tree-reduce-from '+ 1 '(1 (1 1) ((1))))
+ ⇒ 8
+ (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7)))
+ ⇒ ((7 6) ((5 4) 3 2) 1)
+
+ -- Function: -tree-mapreduce (fn folder tree)
+ Apply FN to each element of TREE, and make a list of the results.
+ If elements of TREE are lists themselves, apply FN recursively to
+ elements of these nested lists.
+
+ Then reduce the resulting lists using FOLDER and initial value
+ INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::).
+
+ This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::)
+ after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it
+ only traverse the structure once.
+
+ (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9))))
+ ⇒ (1 2 3 4 5 6 7 8 9)
+ (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3))))
+ ⇒ 9
+ (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3))))
+ ⇒ 3
+
+ -- Function: -tree-mapreduce-from (fn folder init-value tree)
+ Apply FN to each element of TREE, and make a list of the results.
+ If elements of TREE are lists themselves, apply FN recursively to
+ elements of these nested lists.
+
+ Then reduce the resulting lists using FOLDER and initial value
+ INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::).
+
+ This is the same as calling ‘-tree-reduce-from’ (*note
+ -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is
+ twice as fast as it only traverse the structure once.
+
+ (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9))))
+ ⇒ 362880
+ (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3))))
+ ⇒ (2 (4 (8 18) (4 2)) (14 (8 6)))
+ (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam)))))
+ ⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}"
+
+ -- Function: -clone (list)
+ Create a deep copy of LIST. The new list has the same elements and
+ structure but all cons are replaced with new ones. This is useful
+ when you need to clone a structure such as plist or alist.
+
+ (let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b)
+ ⇒ (1 2 3)
+
+
+File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations, Up: Functions
+
+2.12 Threading macros
+=====================
+
+Macros that conditionally combine sequential forms for brevity or
+readability.
+
+ -- Macro: -> (x &optional form &rest more)
+ Thread the expr through the forms. Insert X as the second item in
+ the first form, making a list of it if it is not a list already.
+ If there are more forms, insert the first form as the second item
+ in second form, etc.
+
+ (-> '(2 3 5))
+ ⇒ (2 3 5)
+ (-> '(2 3 5) (append '(8 13)))
+ ⇒ (2 3 5 8 13)
+ (-> '(2 3 5) (append '(8 13)) (-slice 1 -1))
+ ⇒ (3 5 8)
+
+ -- Macro: ->> (x &optional form &rest more)
+ Thread the expr through the forms. Insert X as the last item in
+ the first form, making a list of it if it is not a list already.
+ If there are more forms, insert the first form as the last item in
+ second form, etc.
+
+ (->> '(1 2 3) (-map 'square))
+ ⇒ (1 4 9)
+ (->> '(1 2 3) (-map 'square) (-remove 'even?))
+ ⇒ (1 9)
+ (->> '(1 2 3) (-map 'square) (-reduce '+))
+ ⇒ 14
+
+ -- Macro: --> (x &rest forms)
+ Starting with the value of X, thread each expression through FORMS.
+
+ Insert X at the position signified by the symbol ‘it’ in the first
+ form. If there are more forms, insert the first form at the
+ position signified by ‘it’ in in second form, etc.
+
+ (--> "def" (concat "abc" it "ghi"))
+ ⇒ "abcdefghi"
+ (--> "def" (concat "abc" it "ghi") (upcase it))
+ ⇒ "ABCDEFGHI"
+ (--> "def" (concat "abc" it "ghi") upcase)
+ ⇒ "ABCDEFGHI"
+
+ -- Macro: -as-> (value variable &rest forms)
+ Starting with VALUE, thread VARIABLE through FORMS.
+
+ In the first form, bind VARIABLE to VALUE. In the second form,
+ bind VARIABLE to the result of the first form, and so forth.
+
+ (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var))
+ ⇒ (8)
+ (-as-> 3 my-var 1+)
+ ⇒ 4
+ (-as-> 3 my-var)
+ ⇒ 3
+
+ -- Macro: -some-> (x &optional form &rest more)
+ When expr is non-nil, thread it through the first form (via ‘->’
+ (*note ->::)), and when that result is non-nil, through the next
+ form, etc.
+
+ (-some-> '(2 3 5))
+ ⇒ (2 3 5)
+ (-some-> 5 square)
+ ⇒ 25
+ (-some-> 5 even? square)
+ ⇒ nil
+
+ -- Macro: -some->> (x &optional form &rest more)
+ When expr is non-nil, thread it through the first form (via ‘->>’
+ (*note ->>::)), and when that result is non-nil, through the next
+ form, etc.
+
+ (-some->> '(1 2 3) (-map 'square))
+ ⇒ (1 4 9)
+ (-some->> '(1 3 5) (-last 'even?) (+ 100))
+ ⇒ nil
+ (-some->> '(2 4 6) (-last 'even?) (+ 100))
+ ⇒ 106
+
+ -- Macro: -some--> (expr &rest forms)
+ Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result
+ is non-nil. When EXPR evaluates to non-nil, thread the result
+ through the first of FORMS, and when that result is non-nil, thread
+ it through the next form, etc.
+
+ (-some--> "def" (concat "abc" it "ghi"))
+ ⇒ "abcdefghi"
+ (-some--> nil (concat "abc" it "ghi"))
+ ⇒ nil
+ (-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it))
+ ⇒ ()
+
+ -- Macro: -doto (init &rest forms)
+ Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note
+ ->::). The RESULT of evaluating INIT is threaded through each of
+ FORMS individually using ‘->’ (*note ->::), which see. The return
+ value is RESULT, which FORMS may have modified by side effect.
+
+ (-doto (list 1 2 3) pop pop)
+ ⇒ (3)
+ (-doto (cons 1 2) (setcar 3) (setcdr 4))
+ ⇒ (3 . 4)
+ (gethash 'k (--doto (make-hash-table) (puthash 'k 'v it)))
+ ⇒ v
+
+
+File: dash.info, Node: Binding, Next: Side effects, Prev: Threading macros, Up: Functions
+
+2.13 Binding
+============
+
+Macros that combine ‘let’ and ‘let*’ with destructuring and flow
+control.
+
+ -- Macro: -when-let ((var val) &rest body)
+ If VAL evaluates to non-nil, bind it to VAR and execute body.
+
+ Note: binding is done according to ‘-let’ (*note -let::).
+
+ (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2))
+ ⇒ 5
+ (-when-let ((&plist :foo foo) (list :foo "foo")) foo)
+ ⇒ "foo"
+ (-when-let ((&plist :foo foo) (list :bar "bar")) foo)
+ ⇒ nil
+
+ -- Macro: -when-let* (vars-vals &rest body)
+ If all VALS evaluate to true, bind them to their corresponding VARS
+ and execute body. VARS-VALS should be a list of (VAR VAL) pairs.
+
+ Note: binding is done according to ‘-let*’ (*note -let*::). VALS
+ are evaluated sequentially, and evaluation stops after the first
+ nil VAL is encountered.
+
+ (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z))
+ ⇒ 15
+ (-when-let* ((x 5) (y nil) (z 7)) (+ x y z))
+ ⇒ nil
+
+ -- Macro: -if-let ((var val) then &rest else)
+ If VAL evaluates to non-nil, bind it to VAR and do THEN, otherwise
+ do ELSE.
+
+ Note: binding is done according to ‘-let’ (*note -let::).
+
+ (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7)
+ ⇒ 7
+ (--if-let (even? 4) it nil)
+ ⇒ t
+
+ -- Macro: -if-let* (vars-vals then &rest else)
+ If all VALS evaluate to true, bind them to their corresponding VARS
+ and do THEN, otherwise do ELSE. VARS-VALS should be a list of (VAR
+ VAL) pairs.
+
+ Note: binding is done according to ‘-let*’ (*note -let*::). VALS
+ are evaluated sequentially, and evaluation stops after the first
+ nil VAL is encountered.
+
+ (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo")
+ ⇒ 15
+ (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo")
+ ⇒ "foo"
+ (-if-let* (((_ _ x) '(nil nil 7))) x)
+ ⇒ 7
+
+ -- Macro: -let (varlist &rest body)
+ Bind variables according to VARLIST then eval BODY.
+
+ VARLIST is a list of lists of the form (PATTERN SOURCE). Each
+ PATTERN is matched against the SOURCE "structurally". SOURCE is
+ only evaluated once for each PATTERN. Each PATTERN is matched
+ recursively, and can therefore contain sub-patterns which are
+ matched against corresponding sub-expressions of SOURCE.
+
+ All the SOURCEs are evalled before any symbols are bound (i.e. "in
+ parallel").
+
+ If VARLIST only contains one (PATTERN SOURCE) element, you can
+ optionally specify it using a vector and discarding the outer-most
+ parens. Thus
+
+ (-let ((PATTERN SOURCE)) ...)
+
+ becomes
+
+ (-let [PATTERN SOURCE] ...).
+
+ ‘-let’ (*note -let::) uses a convention of not binding places
+ (symbols) starting with _ whenever it’s possible. You can use this
+ to skip over entries you don’t care about. However, this is not
+ *always* possible (as a result of implementation) and these symbols
+ might get bound to undefined values.
+
+ Following is the overview of supported patterns. Remember that
+ patterns can be matched recursively, so every a, b, aK in the
+ following can be a matching construct and not necessarily a
+ symbol/variable.
+
+ Symbol:
+
+ a - bind the SOURCE to A. This is just like regular ‘let’.
+
+ Conses and lists:
+
+ (a) - bind ‘car’ of cons/list to A
+
+ (a . b) - bind car of cons to A and ‘cdr’ to B
+
+ (a b) - bind car of list to A and ‘cadr’ to B
+
+ (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to
+ A3...
+
+ (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST.
+
+ Vectors:
+
+ [a] - bind 0th element of a non-list sequence to A (works with
+ vectors, strings, bit arrays...)
+
+ [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st
+ to A1, 2nd to A2, ... If the PATTERN is shorter than SOURCE, the
+ values at places not in PATTERN are ignored. If the PATTERN is
+ longer than SOURCE, an ‘error’ is thrown.
+
+ [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the
+ sequence to REST. This is conceptually the same as improper list
+ matching (a1 a2 ... aN . rest)
+
+ Key/value stores:
+
+ (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE plist to aK. If the value is not found, aK is nil. Uses
+ ‘plist-get’ to fetch values.
+
+ (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE alist to aK. If the value is not found, aK is nil. Uses
+ ‘assoc’ to fetch values.
+
+ (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
+ SOURCE hash table to aK. If the value is not found, aK is nil.
+ Uses ‘gethash’ to fetch values.
+
+ Further, special keyword &keys supports "inline" matching of
+ plist-like key-value pairs, similarly to &keys keyword of
+ ‘cl-defun’.
+
+ (a1 a2 ... aN &keys key1 b1 ... keyN bK)
+
+ This binds N values from the list to a1 ... aN, then interprets the
+ cdr as a plist (see key/value matching above).
+
+ A shorthand notation for kv-destructuring exists which allows the
+ patterns be optionally left out and derived from the key name in
+ the following fashion:
+
+ - a key :foo is converted into ‘foo’ pattern, - a key ’bar is
+ converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’
+ pattern.
+
+ That is, the entire value under the key is bound to the derived
+ variable without any further destructuring.
+
+ This is possible only when the form following the key is not a
+ valid pattern (i.e. not a symbol, a cons cell or a vector).
+ Otherwise the matching proceeds as usual and in case of an invalid
+ spec fails with an error.
+
+ Thus the patterns are normalized as follows:
+
+ ;; derive all the missing patterns (&plist :foo ’bar "baz") =>
+ (&plist :foo foo ’bar bar "baz" baz)
+
+ ;; we can specify some but not others (&plist :foo ’bar
+ explicit-bar) => (&plist :foo foo ’bar explicit-bar)
+
+ ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist
+ :foo x)
+
+ ;; nothing happens, we match recursively (&plist :foo (a b c)) =>
+ (&plist :foo (a b c))
+
+ You can name the source using the syntax SYMBOL &as PATTERN. This
+ syntax works with lists (proper or improper), vectors and all types
+ of maps.
+
+ (list &as a b c) (list 1 2 3)
+
+ binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
+
+ Similarly:
+
+ (bounds &as beg . end) (cons 1 2)
+
+ binds BEG to 1, END to 2 and BOUNDS to (1 . 2).
+
+ (items &as first . rest) (list 1 2 3)
+
+ binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
+
+ [vect &as _ b c] [1 2 3]
+
+ binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as
+ usual).
+
+ (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+ binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and
+ &hash.
+
+ This is especially useful when we want to capture the result of a
+ computation and destructure at the same time. Consider the form
+ (function-returning-complex-structure) returning a list of two
+ vectors with two items each. We want to capture this entire result
+ and pass it to another computation, but at the same time we want to
+ get the second item from each vector. We can achieve it with
+ pattern
+
+ (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+ Note: Clojure programmers may know this feature as the ":as
+ binding". The difference is that we put the &as at the front
+ because we need to support improper list binding.
+
+ (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d))
+ ⇒ (1 2 3 4)
+ (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d))
+ ⇒ (1 2 3 (4 5 6))
+ (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar))
+ ⇒ (1 2)
+
+ -- Macro: -let* (varlist &rest body)
+ Bind variables according to VARLIST then eval BODY.
+
+ VARLIST is a list of lists of the form (PATTERN SOURCE). Each
+ PATTERN is matched against the SOURCE structurally. SOURCE is only
+ evaluated once for each PATTERN.
+
+ Each SOURCE can refer to the symbols already bound by this VARLIST.
+ This is useful if you want to destructure SOURCE recursively but
+ also want to name the intermediate structures.
+
+ See ‘-let’ (*note -let::) for the list of all possible patterns.
+
+ (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d))
+ ⇒ (1 2 3 4)
+ (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d))
+ ⇒ (1 (2 . 3) 2 3)
+ (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar))
+ ⇒ (1 a b c (a b c))
+
+ -- Macro: -lambda (match-form &rest body)
+ Return a lambda which destructures its input as MATCH-FORM and
+ executes BODY.
+
+ Note that you have to enclose the MATCH-FORM in a pair of parens,
+ such that:
+
+ (-lambda (x) body) (-lambda (x y ...) body)
+
+ has the usual semantics of ‘lambda’. Furthermore, these get
+ translated into normal ‘lambda’, so there is no performance
+ penalty.
+
+ See ‘-let’ (*note -let::) for a description of the destructuring
+ mechanism.
+
+ (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6)))
+ ⇒ (3 7 11)
+ (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6]))
+ ⇒ (3 7 11)
+ (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6))
+ ⇒ (2 3 5 6)
+
+ -- Macro: -setq ([match-form val] ...)
+ Bind each MATCH-FORM to the value of its VAL.
+
+ MATCH-FORM destructuring is done according to the rules of ‘-let’
+ (*note -let::).
+
+ This macro allows you to bind multiple variables by destructuring
+ the value, so for example:
+
+ (-setq (a b) x (&plist :c c) plist)
+
+ expands roughly speaking to the following code
+
+ (setq a (car x) b (cadr x) c (plist-get plist :c))
+
+ Care is taken to only evaluate each VAL once so that in case of
+ multiple assignments it does not cause unexpected side effects.
+
+ (let (a) (-setq a 1) a)
+ ⇒ 1
+ (let (a b) (-setq (a b) (list 1 2)) (list a b))
+ ⇒ (1 2)
+ (let (c) (-setq (&plist :c c) (list :c "c")) c)
+ ⇒ "c"
+
+
+File: dash.info, Node: Side effects, Next: Destructive operations, Prev: Binding, Up: Functions
+
+2.14 Side effects
+=================
+
+Functions iterating over lists for side effect only.
+
+ -- Function: -each (list fn)
+ Call FN on each element of LIST. Return nil; this function is
+ intended for side effects.
+
+ Its anaphoric counterpart is ‘--each’.
+
+ For access to the current element’s index in LIST, see
+ ‘-each-indexed’ (*note -each-indexed::).
+
+ (let (l) (-each '(1 2 3) (lambda (x) (push x l))) l)
+ ⇒ (3 2 1)
+ (let (l) (--each '(1 2 3) (push it l)) l)
+ ⇒ (3 2 1)
+ (-each '(1 2 3) #'identity)
+ ⇒ nil
+
+ -- Function: -each-while (list pred fn)
+ Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil. Once
+ an ITEM is reached for which PRED returns nil, FN is no longer
+ called. Return nil; this function is intended for side effects.
+
+ Its anaphoric counterpart is ‘--each-while’.
+
+ (let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
+ ⇒ (4 2)
+ (let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l)
+ ⇒ (2 1)
+ (let ((s 0)) (--each-while '(1 3 4 5) (< it 5) (setq s (+ s it))) s)
+ ⇒ 8
+
+ -- Function: -each-indexed (list fn)
+ Call FN on each index and element of LIST. For each ITEM at INDEX
+ in LIST, call (funcall FN INDEX ITEM). Return nil; this function
+ is intended for side effects.
+
+ See also: ‘-map-indexed’ (*note -map-indexed::).
+
+ (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l)
+ ⇒ ((c 2) (b 1) (a 0))
+ (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l)
+ ⇒ ((c 2) (b 1) (a 0))
+ (let (l) (--each-indexed () (push it l)) l)
+ ⇒ ()
+
+ -- Function: -each-r (list fn)
+ Call FN on each element of LIST in reversed order. Return nil;
+ this function is intended for side effects.
+
+ Its anaphoric counterpart is ‘--each-r’.
+
+ (let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l)
+ ⇒ (1 2 3)
+ (let (l) (--each-r '(1 2 3) (push it l)) l)
+ ⇒ (1 2 3)
+ (-each-r '(1 2 3) #'identity)
+ ⇒ nil
+
+ -- Function: -each-r-while (list pred fn)
+ Call FN on each ITEM in reversed LIST, while (PRED ITEM) is
+ non-nil. Once an ITEM is reached for which PRED returns nil, FN is
+ no longer called. Return nil; this function is intended for side
+ effects.
+
+ Its anaphoric counterpart is ‘--each-r-while’.
+
+ (let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
+ ⇒ (6)
+ (let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l)
+ ⇒ (3 4)
+ (let ((s 0)) (--each-r-while '(1 2 3 5) (> it 1) (setq s (+ s it))) s)
+ ⇒ 10
+
+ -- Function: -dotimes (num fn)
+ Call FN NUM times, presumably for side effects. FN is called with
+ a single argument on successive integers running from 0, inclusive,
+ to NUM, exclusive. FN is not called if NUM is less than 1.
+
+ This function’s anaphoric counterpart is ‘--dotimes’.
+
+ (let (s) (-dotimes 3 (lambda (n) (push n s))) s)
+ ⇒ (2 1 0)
+ (let (s) (-dotimes 0 (lambda (n) (push n s))) s)
+ ⇒ ()
+ (let (s) (--dotimes 5 (push it s)) s)
+ ⇒ (4 3 2 1 0)
+
+
+File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side effects, Up: Functions
+
+2.15 Destructive operations
+===========================
+
+Macros that modify variables holding lists.
+
+ -- Macro: !cons (car cdr)
+ Destructive: Set CDR to the cons of CAR and CDR.
+
+ (let (l) (!cons 5 l) l)
+ ⇒ (5)
+ (let ((l '(3))) (!cons 5 l) l)
+ ⇒ (5 3)
+
+ -- Macro: !cdr (list)
+ Destructive: Set LIST to the cdr of LIST.
+
+ (let ((l '(3))) (!cdr l) l)
+ ⇒ ()
+ (let ((l '(3 5))) (!cdr l) l)
+ ⇒ (5)
+
+
+File: dash.info, Node: Function combinators, Prev: Destructive operations, Up: Functions
+
+2.16 Function combinators
+=========================
+
+Functions that manipulate and compose other functions.
+
+ -- Function: -partial (fun &rest args)
+ Return a function that is a partial application of FUN to ARGS.
+ ARGS is a list of the first N arguments to pass to FUN. The result
+ is a new function which does the same as FUN, except that the first
+ N arguments are fixed at the values with which this function was
+ called.
+
+ (funcall (-partial #'+ 5))
+ ⇒ 5
+ (funcall (-partial #'- 5) 3)
+ ⇒ 2
+ (funcall (-partial #'+ 5 2) 3)
+ ⇒ 10
+
+ -- Function: -rpartial (fn &rest args)
+ Return a function that is a partial application of FN to ARGS.
+ ARGS is a list of the last N arguments to pass to FN. The result
+ is a new function which does the same as FN, except that the last N
+ arguments are fixed at the values with which this function was
+ called. This is like ‘-partial’ (*note -partial::), except the
+ arguments are fixed starting from the right rather than the left.
+
+ (funcall (-rpartial #'- 5))
+ ⇒ -5
+ (funcall (-rpartial #'- 5) 8)
+ ⇒ 3
+ (funcall (-rpartial #'- 5 2) 10)
+ ⇒ 3
+
+ -- Function: -juxt (&rest fns)
+ Return a function that is the juxtaposition of FNS. The returned
+ function takes a variable number of ARGS, applies each of FNS in
+ turn to ARGS, and returns the list of results.
+
+ (funcall (-juxt) 1 2)
+ ⇒ ()
+ (funcall (-juxt #'+ #'- #'* #'/) 7 5)
+ ⇒ (12 2 35 1)
+ (mapcar (-juxt #'number-to-string #'1+) '(1 2))
+ ⇒ (("1" 2) ("2" 3))
+
+ -- Function: -compose (&rest fns)
+ Compose FNS into a single composite function. Return a function
+ that takes a variable number of ARGS, applies the last function in
+ FNS to ARGS, and returns the result of calling each remaining
+ function on the result of the previous function, right-to-left. If
+ no FNS are given, return a variadic ‘identity’ function.
+
+ (funcall (-compose #'- #'1+ #'+) 1 2 3)
+ ⇒ -7
+ (funcall (-compose #'identity #'1+) 3)
+ ⇒ 4
+ (mapcar (-compose #'not #'stringp) '(nil ""))
+ ⇒ (t nil)
+
+ -- Function: -applify (fn)
+ Return a function that applies FN to a single list of args. This
+ changes the arity of FN from taking N distinct arguments to taking
+ 1 argument which is a list of N arguments.
+
+ (funcall (-applify #'+) nil)
+ ⇒ 0
+ (mapcar (-applify #'+) '((1 1 1) (1 2 3) (5 5 5)))
+ ⇒ (3 6 15)
+ (funcall (-applify #'<) '(3 6))
+ ⇒ t
+
+ -- Function: -on (op trans)
+ Return a function that calls TRANS on each arg and OP on the
+ results. The returned function takes a variable number of
+ arguments, calls the function TRANS on each one in turn, and then
+ passes those results as the list of arguments to OP, in the same
+ order.
+
+ For example, the following pairs of expressions are morally
+ equivalent:
+
+ (funcall (-on #’+ #’1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3)) (funcall
+ (-on #’+ #’1+)) = (+)
+
+ (-sort (-on #'< #'length) '((1 2 3) (1) (1 2)))
+ ⇒ ((1) (1 2) (1 2 3))
+ (funcall (-on #'min #'string-to-number) "22" "2" "1" "12")
+ ⇒ 1
+ (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2)))
+ ⇒ (4)
+
+ -- Function: -flip (fn)
+ Return a function that calls FN with its arguments reversed. The
+ returned function takes the same number of arguments as FN.
+
+ For example, the following two expressions are morally equivalent:
+
+ (funcall (-flip #’-) 1 2) = (- 2 1)
+
+ See also: ‘-rotate-args’ (*note -rotate-args::).
+
+ (-sort (-flip #'<) '(4 3 6 1))
+ ⇒ (6 4 3 1)
+ (funcall (-flip #'-) 3 2 1 10)
+ ⇒ 4
+ (funcall (-flip #'1+) 1)
+ ⇒ 2
+
+ -- Function: -rotate-args (n fn)
+ Return a function that calls FN with args rotated N places to the
+ right. The returned function takes the same number of arguments as
+ FN, rotates the list of arguments N places to the right (left if N
+ is negative) just like ‘-rotate’ (*note -rotate::), and applies FN
+ to the result.
+
+ See also: ‘-flip’ (*note -flip::).
+
+ (funcall (-rotate-args -1 #'list) 1 2 3 4)
+ ⇒ (2 3 4 1)
+ (funcall (-rotate-args 1 #'-) 1 10 100)
+ ⇒ 89
+ (funcall (-rotate-args 2 #'list) 3 4 5 1 2)
+ ⇒ (1 2 3 4 5)
+
+ -- Function: -const (c)
+ Return a function that returns C ignoring any additional arguments.
+
+ In types: a -> b -> a
+
+ (funcall (-const 2) 1 3 "foo")
+ ⇒ 2
+ (mapcar (-const 1) '("a" "b" "c" "d"))
+ ⇒ (1 1 1 1)
+ (-sum (mapcar (-const 1) '("a" "b" "c" "d")))
+ ⇒ 4
+
+ -- Macro: -cut (&rest params)
+ Take n-ary function and n arguments and specialize some of them.
+ Arguments denoted by <> will be left unspecialized.
+
+ See SRFI-26 for detailed description.
+
+ (funcall (-cut list 1 <> 3 <> 5) 2 4)
+ ⇒ (1 2 3 4 5)
+ (-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x))))
+ ⇒ (6 4 0.2)
+ (-map (-cut <> 1 2 3) '(list vector string))
+ ⇒ ((1 2 3) [1 2 3] "\1\2\3")
+
+ -- Function: -not (pred)
+ Return a predicate that negates the result of PRED. The returned
+ predicate passes its arguments to PRED. If PRED returns nil, the
+ result is non-nil; otherwise the result is nil.
+
+ See also: ‘-andfn’ (*note -andfn::) and ‘-orfn’ (*note -orfn::).
+
+ (funcall (-not #'numberp) "5")
+ ⇒ t
+ (-sort (-not #'<) '(5 2 1 0 6))
+ ⇒ (6 5 2 1 0)
+ (-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8))
+ ⇒ (1 2 3 4)
+
+ -- Function: -orfn (&rest preds)
+ Return a predicate that returns the first non-nil result of PREDS.
+ The returned predicate takes a variable number of arguments, passes
+ them to each predicate in PREDS in turn until one of them returns
+ non-nil, and returns that non-nil result without calling the
+ remaining PREDS. If all PREDS return nil, or if no PREDS are
+ given, the returned predicate returns nil.
+
+ See also: ‘-andfn’ (*note -andfn::) and ‘-not’ (*note -not::).
+
+ (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t))
+ ⇒ (1 nil t)
+ (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe")
+ ⇒ 1
+ (funcall (-orfn #'= #'+) 1 1)
+ ⇒ t
+
+ -- Function: -andfn (&rest preds)
+ Return a predicate that returns non-nil if all PREDS do so. The
+ returned predicate P takes a variable number of arguments and
+ passes them to each predicate in PREDS in turn. If any one of
+ PREDS returns nil, P also returns nil without calling the remaining
+ PREDS. If all PREDS return non-nil, P returns the last such value.
+ If no PREDS are given, P always returns non-nil.
+
+ See also: ‘-orfn’ (*note -orfn::) and ‘-not’ (*note -not::).
+
+ (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2))
+ ⇒ (1 2)
+ (mapcar (-andfn #'numberp #'1+) '(a 1 b 6))
+ ⇒ (nil 2 nil 7)
+ (funcall (-andfn #'= #'+) 1 1)
+ ⇒ 2
+
+ -- Function: -iteratefn (fn n)
+ Return a function FN composed N times with itself.
+
+ FN is a unary function. If you need to use a function of higher
+ arity, use ‘-applify’ (*note -applify::) first to turn it into a
+ unary function.
+
+ With n = 0, this acts as identity function.
+
+ In types: (a -> a) -> Int -> a -> a.
+
+ This function satisfies the following law:
+
+ (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init
+ (1+ n))).
+
+ (funcall (-iteratefn (lambda (x) (* x x)) 3) 2)
+ ⇒ 256
+ (funcall (-iteratefn '1+ 3) 1)
+ ⇒ 4
+ (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5))
+ ⇒ (4 5)
+
+ -- Function: -fixfn (fn &optional equal-test halt-test)
+ Return a function that computes the (least) fixpoint of FN.
+
+ FN must be a unary function. The returned lambda takes a single
+ argument, X, the initial value for the fixpoint iteration. The
+ iteration halts when either of the following conditions is
+ satisfied:
+
+ 1. Iteration converges to the fixpoint, with equality being tested
+ using EQUAL-TEST. If EQUAL-TEST is not specified, ‘equal’ is used.
+ For functions over the floating point numbers, it may be necessary
+ to provide an appropriate approximate comparison test.
+
+ 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a
+ simple counter that returns t after ‘-fixfn-max-iterations’, to
+ guard against infinite iteration. Otherwise, HALT-TEST must be a
+ function that accepts a single argument, the current value of X,
+ and returns non-nil as long as iteration should continue. In this
+ way, a more sophisticated convergence test may be supplied by the
+ caller.
+
+ The return value of the lambda is either the fixpoint or, if
+ iteration halted before converging, a cons with car ‘halted’ and
+ cdr the final output from HALT-TEST.
+
+ In types: (a -> a) -> a -> a.
+
+ (funcall (-fixfn #'cos #'approx=) 0.7)
+ ⇒ 0.7390851332151607
+ (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0)
+ ⇒ 1.8555845286409378
+ (funcall (-fixfn #'sin #'approx=) 0.1)
+ ⇒ (halted . t)
+
+ -- Function: -prodfn (&rest fns)
+ Take a list of n functions and return a function that takes a list
+ of length n, applying i-th function to i-th element of the input
+ list. Returns a list of length n.
+
+ In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
+
+ This function satisfies the following laws:
+
+ (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn
+ (-compose f f’) (-compose g g’) ...) (-prodfn f g ...) = (-juxt
+ (-compose f (-partial ’nth 0)) (-compose g (-partial ’nth 1)) ...)
+ (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose f
+ f’) (-compose g g’) ...) (-compose (-partial ’nth n) (-prod f1 f2
+ ...)) = (-compose fn (-partial ’nth n))
+
+ (funcall (-prodfn '1+ '1- 'number-to-string) '(1 2 3))
+ ⇒ (2 1 "3")
+ (-map (-prodfn '1+ '1-) '((1 2) (3 4) (5 6) (7 8)))
+ ⇒ ((2 1) (4 3) (6 5) (8 7))
+ (apply '+ (funcall (-prodfn 'length 'string-to-number) '((1 2 3) "15")))
+ ⇒ 18
+
+
+File: dash.info, Node: Development, Next: FDL, Prev: Functions, Up: Top
+
+3 Development
+*************
+
+The Dash repository is hosted on GitHub at
+<https://github.com/magnars/dash.el>.
+
+* Menu:
+
+* Contribute:: How to contribute.
+* Contributors:: List of contributors.
+
+
+File: dash.info, Node: Contribute, Next: Contributors, Up: Development
+
+3.1 Contribute
+==============
+
+Yes, please do. Pure functions in the list manipulation realm only,
+please. There’s a suite of examples/tests in ‘dev/examples.el’, so
+remember to add tests for your additions, or they may get broken later.
+
+ Run the tests with ‘make check’. Regenerate the docs with ‘make
+docs’. Contributors are encouraged to install these commands as a Git
+pre-commit hook, so that the tests are always running and the docs are
+always in sync:
+
+ $ cp dev/pre-commit.sh .git/hooks/pre-commit
+
+ Oh, and don’t edit ‘README.md’ or ‘dash.texi’ directly, as they are
+auto-generated. Instead, change their respective templates
+‘readme-template.md’ or ‘dash-template.texi’.
+
+ To ensure that Dash can be distributed with GNU ELPA or Emacs, we
+require that all contributors assign copyright to the Free Software
+Foundation. For more on this, *note (emacs)Copyright Assignment::.
+
+
+File: dash.info, Node: Contributors, Prev: Contribute, Up: Development
+
+3.2 Contributors
+================
+
+ • Matus Goljer (https://github.com/Fuco1) contributed lots of
+ features and functions.
+ • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’.
+ • tali713 (https://github.com/tali713) is the author of ‘-applify’.
+ • Víctor M. Valenzuela (https://github.com/vemv) contributed
+ ‘-repeat’.
+ • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’.
+ • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’,
+ ‘-first-item’, and ‘-last-item’.
+ • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’,
+ ‘-when-let’, and ‘-insert-at’.
+ • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’,
+ ‘-product’, and ‘-same-items?’.
+ • Christina Whyte (https://github.com/kurisuwhyte) contributed
+ ‘-compose’.
+ • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’,
+ ‘-pad’, ‘-annotate’, ‘-zip-fill’, and a variadic version of ‘-zip’.
+ • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’
+ family use ‘-let’ destructuring and improved the script for
+ generating documentation.
+ • Mark Oteiza (https://github.com/holomorph) contributed ‘-iota’ and
+ the script to create an Info manual.
+ • Vasilij Schneidermann (https://github.com/wasamasa) contributed
+ ‘-some’.
+ • William West (https://github.com/occidens) made ‘-fixfn’ more
+ robust at handling floats.
+ • Cam Saul (https://github.com/camsaul) contributed ‘-some->’,
+ ‘-some->>’, and ‘-some-->’.
+ • Basil L. Contovounesios (https://github.com/basil-conto)
+ contributed ‘-common-prefix’, ‘-common-suffix’, and various other
+ improvements.
+ • Paul Pogonyshev (https://github.com/doublep) contributed ‘-each-r’
+ and ‘-each-r-while’.
+
+ Thanks!
+
+ New contributors are very welcome. *Note Contribute::.
+
+
+File: dash.info, Node: FDL, Next: GPL, Prev: Development, Up: Top
+
+Appendix A GNU Free Documentation License
+*****************************************
+
+ Version 1.3, 3 November 2008
+
+ Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+ <https://fsf.org/>
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ 0. PREAMBLE
+
+ The purpose of this License is to make a manual, textbook, or other
+ functional and useful document “free†in the sense of freedom: to
+ assure everyone the effective freedom to copy and redistribute it,
+ with or without modifying it, either commercially or
+ noncommercially. Secondarily, this License preserves for the
+ author and publisher a way to get credit for their work, while not
+ being considered responsible for modifications made by others.
+
+ This License is a kind of “copyleftâ€, which means that derivative
+ works of the document must themselves be free in the same sense.
+ It complements the GNU General Public License, which is a copyleft
+ license designed for free software.
+
+ We have designed this License in order to use it for manuals for
+ free software, because free software needs free documentation: a
+ free program should come with manuals providing the same freedoms
+ that the software does. But this License is not limited to
+ software manuals; it can be used for any textual work, regardless
+ of subject matter or whether it is published as a printed book. We
+ recommend this License principally for works whose purpose is
+ instruction or reference.
+
+ 1. APPLICABILITY AND DEFINITIONS
+
+ This License applies to any manual or other work, in any medium,
+ that contains a notice placed by the copyright holder saying it can
+ be distributed under the terms of this License. Such a notice
+ grants a world-wide, royalty-free license, unlimited in duration,
+ to use that work under the conditions stated herein. The
+ “Documentâ€, below, refers to any such manual or work. Any member
+ of the public is a licensee, and is addressed as “youâ€. You accept
+ the license if you copy, modify or distribute the work in a way
+ requiring permission under copyright law.
+
+ A “Modified Version†of the Document means any work containing the
+ Document or a portion of it, either copied verbatim, or with
+ modifications and/or translated into another language.
+
+ A “Secondary Section†is a named appendix or a front-matter section
+ of the Document that deals exclusively with the relationship of the
+ publishers or authors of the Document to the Document’s overall
+ subject (or to related matters) and contains nothing that could
+ fall directly within that overall subject. (Thus, if the Document
+ is in part a textbook of mathematics, a Secondary Section may not
+ explain any mathematics.) The relationship could be a matter of
+ historical connection with the subject or with related matters, or
+ of legal, commercial, philosophical, ethical or political position
+ regarding them.
+
+ The “Invariant Sections†are certain Secondary Sections whose
+ titles are designated, as being those of Invariant Sections, in the
+ notice that says that the Document is released under this License.
+ If a section does not fit the above definition of Secondary then it
+ is not allowed to be designated as Invariant. The Document may
+ contain zero Invariant Sections. If the Document does not identify
+ any Invariant Sections then there are none.
+
+ The “Cover Texts†are certain short passages of text that are
+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
+ that says that the Document is released under this License. A
+ Front-Cover Text may be at most 5 words, and a Back-Cover Text may
+ be at most 25 words.
+
+ A “Transparent†copy of the Document means a machine-readable copy,
+ represented in a format whose specification is available to the
+ general public, that is suitable for revising the document
+ straightforwardly with generic text editors or (for images composed
+ of pixels) generic paint programs or (for drawings) some widely
+ available drawing editor, and that is suitable for input to text
+ formatters or for automatic translation to a variety of formats
+ suitable for input to text formatters. A copy made in an otherwise
+ Transparent file format whose markup, or absence of markup, has
+ been arranged to thwart or discourage subsequent modification by
+ readers is not Transparent. An image format is not Transparent if
+ used for any substantial amount of text. A copy that is not
+ “Transparent†is called “Opaqueâ€.
+
+ Examples of suitable formats for Transparent copies include plain
+ ASCII without markup, Texinfo input format, LaTeX input format,
+ SGML or XML using a publicly available DTD, and standard-conforming
+ simple HTML, PostScript or PDF designed for human modification.
+ Examples of transparent image formats include PNG, XCF and JPG.
+ Opaque formats include proprietary formats that can be read and
+ edited only by proprietary word processors, SGML or XML for which
+ the DTD and/or processing tools are not generally available, and
+ the machine-generated HTML, PostScript or PDF produced by some word
+ processors for output purposes only.
+
+ The “Title Page†means, for a printed book, the title page itself,
+ plus such following pages as are needed to hold, legibly, the
+ material this License requires to appear in the title page. For
+ works in formats which do not have any title page as such, “Title
+ Page†means the text near the most prominent appearance of the
+ work’s title, preceding the beginning of the body of the text.
+
+ The “publisher†means any person or entity that distributes copies
+ of the Document to the public.
+
+ A section “Entitled XYZ†means a named subunit of the Document
+ whose title either is precisely XYZ or contains XYZ in parentheses
+ following text that translates XYZ in another language. (Here XYZ
+ stands for a specific section name mentioned below, such as
+ “Acknowledgementsâ€, “Dedicationsâ€, “Endorsementsâ€, or “Historyâ€.)
+ To “Preserve the Title†of such a section when you modify the
+ Document means that it remains a section “Entitled XYZ†according
+ to this definition.
+
+ The Document may include Warranty Disclaimers next to the notice
+ which states that this License applies to the Document. These
+ Warranty Disclaimers are considered to be included by reference in
+ this License, but only as regards disclaiming warranties: any other
+ implication that these Warranty Disclaimers may have is void and
+ has no effect on the meaning of this License.
+
+ 2. VERBATIM COPYING
+
+ You may copy and distribute the Document in any medium, either
+ commercially or noncommercially, provided that this License, the
+ copyright notices, and the license notice saying this License
+ applies to the Document are reproduced in all copies, and that you
+ add no other conditions whatsoever to those of this License. You
+ may not use technical measures to obstruct or control the reading
+ or further copying of the copies you make or distribute. However,
+ you may accept compensation in exchange for copies. If you
+ distribute a large enough number of copies you must also follow the
+ conditions in section 3.
+
+ You may also lend copies, under the same conditions stated above,
+ and you may publicly display copies.
+
+ 3. COPYING IN QUANTITY
+
+ If you publish printed copies (or copies in media that commonly
+ have printed covers) of the Document, numbering more than 100, and
+ the Document’s license notice requires Cover Texts, you must
+ enclose the copies in covers that carry, clearly and legibly, all
+ these Cover Texts: Front-Cover Texts on the front cover, and
+ Back-Cover Texts on the back cover. Both covers must also clearly
+ and legibly identify you as the publisher of these copies. The
+ front cover must present the full title with all words of the title
+ equally prominent and visible. You may add other material on the
+ covers in addition. Copying with changes limited to the covers, as
+ long as they preserve the title of the Document and satisfy these
+ conditions, can be treated as verbatim copying in other respects.
+
+ If the required texts for either cover are too voluminous to fit
+ legibly, you should put the first ones listed (as many as fit
+ reasonably) on the actual cover, and continue the rest onto
+ adjacent pages.
+
+ If you publish or distribute Opaque copies of the Document
+ numbering more than 100, you must either include a machine-readable
+ Transparent copy along with each Opaque copy, or state in or with
+ each Opaque copy a computer-network location from which the general
+ network-using public has access to download using public-standard
+ network protocols a complete Transparent copy of the Document, free
+ of added material. If you use the latter option, you must take
+ reasonably prudent steps, when you begin distribution of Opaque
+ copies in quantity, to ensure that this Transparent copy will
+ remain thus accessible at the stated location until at least one
+ year after the last time you distribute an Opaque copy (directly or
+ through your agents or retailers) of that edition to the public.
+
+ It is requested, but not required, that you contact the authors of
+ the Document well before redistributing any large number of copies,
+ to give them a chance to provide you with an updated version of the
+ Document.
+
+ 4. MODIFICATIONS
+
+ You may copy and distribute a Modified Version of the Document
+ under the conditions of sections 2 and 3 above, provided that you
+ release the Modified Version under precisely this License, with the
+ Modified Version filling the role of the Document, thus licensing
+ distribution and modification of the Modified Version to whoever
+ possesses a copy of it. In addition, you must do these things in
+ the Modified Version:
+
+ A. Use in the Title Page (and on the covers, if any) a title
+ distinct from that of the Document, and from those of previous
+ versions (which should, if there were any, be listed in the
+ History section of the Document). You may use the same title
+ as a previous version if the original publisher of that
+ version gives permission.
+
+ B. List on the Title Page, as authors, one or more persons or
+ entities responsible for authorship of the modifications in
+ the Modified Version, together with at least five of the
+ principal authors of the Document (all of its principal
+ authors, if it has fewer than five), unless they release you
+ from this requirement.
+
+ C. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+
+ D. Preserve all the copyright notices of the Document.
+
+ E. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+
+ F. Include, immediately after the copyright notices, a license
+ notice giving the public permission to use the Modified
+ Version under the terms of this License, in the form shown in
+ the Addendum below.
+
+ G. Preserve in that license notice the full lists of Invariant
+ Sections and required Cover Texts given in the Document’s
+ license notice.
+
+ H. Include an unaltered copy of this License.
+
+ I. Preserve the section Entitled “Historyâ€, Preserve its Title,
+ and add to it an item stating at least the title, year, new
+ authors, and publisher of the Modified Version as given on the
+ Title Page. If there is no section Entitled “History†in the
+ Document, create one stating the title, year, authors, and
+ publisher of the Document as given on its Title Page, then add
+ an item describing the Modified Version as stated in the
+ previous sentence.
+
+ J. Preserve the network location, if any, given in the Document
+ for public access to a Transparent copy of the Document, and
+ likewise the network locations given in the Document for
+ previous versions it was based on. These may be placed in the
+ “History†section. You may omit a network location for a work
+ that was published at least four years before the Document
+ itself, or if the original publisher of the version it refers
+ to gives permission.
+
+ K. For any section Entitled “Acknowledgements†or “Dedicationsâ€,
+ Preserve the Title of the section, and preserve in the section
+ all the substance and tone of each of the contributor
+ acknowledgements and/or dedications given therein.
+
+ L. Preserve all the Invariant Sections of the Document, unaltered
+ in their text and in their titles. Section numbers or the
+ equivalent are not considered part of the section titles.
+
+ M. Delete any section Entitled “Endorsementsâ€. Such a section
+ may not be included in the Modified Version.
+
+ N. Do not retitle any existing section to be Entitled
+ “Endorsements†or to conflict in title with any Invariant
+ Section.
+
+ O. Preserve any Warranty Disclaimers.
+
+ If the Modified Version includes new front-matter sections or
+ appendices that qualify as Secondary Sections and contain no
+ material copied from the Document, you may at your option designate
+ some or all of these sections as invariant. To do this, add their
+ titles to the list of Invariant Sections in the Modified Version’s
+ license notice. These titles must be distinct from any other
+ section titles.
+
+ You may add a section Entitled “Endorsementsâ€, provided it contains
+ nothing but endorsements of your Modified Version by various
+ parties—for example, statements of peer review or that the text has
+ been approved by an organization as the authoritative definition of
+ a standard.
+
+ You may add a passage of up to five words as a Front-Cover Text,
+ and a passage of up to 25 words as a Back-Cover Text, to the end of
+ the list of Cover Texts in the Modified Version. Only one passage
+ of Front-Cover Text and one of Back-Cover Text may be added by (or
+ through arrangements made by) any one entity. If the Document
+ already includes a cover text for the same cover, previously added
+ by you or by arrangement made by the same entity you are acting on
+ behalf of, you may not add another; but you may replace the old
+ one, on explicit permission from the previous publisher that added
+ the old one.
+
+ The author(s) and publisher(s) of the Document do not by this
+ License give permission to use their names for publicity for or to
+ assert or imply endorsement of any Modified Version.
+
+ 5. COMBINING DOCUMENTS
+
+ You may combine the Document with other documents released under
+ this License, under the terms defined in section 4 above for
+ modified versions, provided that you include in the combination all
+ of the Invariant Sections of all of the original documents,
+ unmodified, and list them all as Invariant Sections of your
+ combined work in its license notice, and that you preserve all
+ their Warranty Disclaimers.
+
+ The combined work need only contain one copy of this License, and
+ multiple identical Invariant Sections may be replaced with a single
+ copy. If there are multiple Invariant Sections with the same name
+ but different contents, make the title of each such section unique
+ by adding at the end of it, in parentheses, the name of the
+ original author or publisher of that section if known, or else a
+ unique number. Make the same adjustment to the section titles in
+ the list of Invariant Sections in the license notice of the
+ combined work.
+
+ In the combination, you must combine any sections Entitled
+ “History†in the various original documents, forming one section
+ Entitled “Historyâ€; likewise combine any sections Entitled
+ “Acknowledgementsâ€, and any sections Entitled “Dedicationsâ€. You
+ must delete all sections Entitled “Endorsements.â€
+
+ 6. COLLECTIONS OF DOCUMENTS
+
+ You may make a collection consisting of the Document and other
+ documents released under this License, and replace the individual
+ copies of this License in the various documents with a single copy
+ that is included in the collection, provided that you follow the
+ rules of this License for verbatim copying of each of the documents
+ in all other respects.
+
+ You may extract a single document from such a collection, and
+ distribute it individually under this License, provided you insert
+ a copy of this License into the extracted document, and follow this
+ License in all other respects regarding verbatim copying of that
+ document.
+
+ 7. AGGREGATION WITH INDEPENDENT WORKS
+
+ A compilation of the Document or its derivatives with other
+ separate and independent documents or works, in or on a volume of a
+ storage or distribution medium, is called an “aggregate†if the
+ copyright resulting from the compilation is not used to limit the
+ legal rights of the compilation’s users beyond what the individual
+ works permit. When the Document is included in an aggregate, this
+ License does not apply to the other works in the aggregate which
+ are not themselves derivative works of the Document.
+
+ If the Cover Text requirement of section 3 is applicable to these
+ copies of the Document, then if the Document is less than one half
+ of the entire aggregate, the Document’s Cover Texts may be placed
+ on covers that bracket the Document within the aggregate, or the
+ electronic equivalent of covers if the Document is in electronic
+ form. Otherwise they must appear on printed covers that bracket
+ the whole aggregate.
+
+ 8. TRANSLATION
+
+ Translation is considered a kind of modification, so you may
+ distribute translations of the Document under the terms of section
+ 4. Replacing Invariant Sections with translations requires special
+ permission from their copyright holders, but you may include
+ translations of some or all Invariant Sections in addition to the
+ original versions of these Invariant Sections. You may include a
+ translation of this License, and all the license notices in the
+ Document, and any Warranty Disclaimers, provided that you also
+ include the original English version of this License and the
+ original versions of those notices and disclaimers. In case of a
+ disagreement between the translation and the original version of
+ this License or a notice or disclaimer, the original version will
+ prevail.
+
+ If a section in the Document is Entitled “Acknowledgementsâ€,
+ “Dedicationsâ€, or “Historyâ€, the requirement (section 4) to
+ Preserve its Title (section 1) will typically require changing the
+ actual title.
+
+ 9. TERMINATION
+
+ You may not copy, modify, sublicense, or distribute the Document
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, or distribute it is void,
+ and will automatically terminate your rights under this License.
+
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly and
+ finally terminates your license, and (b) permanently, if the
+ copyright holder fails to notify you of the violation by some
+ reasonable means prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you have
+ received notice of violation of this License (for any work) from
+ that copyright holder, and you cure the violation prior to 30 days
+ after your receipt of the notice.
+
+ Termination of your rights under this section does not terminate
+ the licenses of parties who have received copies or rights from you
+ under this License. If your rights have been terminated and not
+ permanently reinstated, receipt of a copy of some or all of the
+ same material does not give you any rights to use it.
+
+ 10. FUTURE REVISIONS OF THIS LICENSE
+
+ The Free Software Foundation may publish new, revised versions of
+ the GNU Free Documentation License from time to time. Such new
+ versions will be similar in spirit to the present version, but may
+ differ in detail to address new problems or concerns. See
+ <https://www.gnu.org/licenses/>.
+
+ Each version of the License is given a distinguishing version
+ number. If the Document specifies that a particular numbered
+ version of this License “or any later version†applies to it, you
+ have the option of following the terms and conditions either of
+ that specified version or of any later version that has been
+ published (not as a draft) by the Free Software Foundation. If the
+ Document does not specify a version number of this License, you may
+ choose any version ever published (not as a draft) by the Free
+ Software Foundation. If the Document specifies that a proxy can
+ decide which future versions of this License can be used, that
+ proxy’s public statement of acceptance of a version permanently
+ authorizes you to choose that version for the Document.
+
+ 11. RELICENSING
+
+ “Massive Multiauthor Collaboration Site†(or “MMC Siteâ€) means any
+ World Wide Web server that publishes copyrightable works and also
+ provides prominent facilities for anybody to edit those works. A
+ public wiki that anybody can edit is an example of such a server.
+ A “Massive Multiauthor Collaboration†(or “MMCâ€) contained in the
+ site means any set of copyrightable works thus published on the MMC
+ site.
+
+ “CC-BY-SA†means the Creative Commons Attribution-Share Alike 3.0
+ license published by Creative Commons Corporation, a not-for-profit
+ corporation with a principal place of business in San Francisco,
+ California, as well as future copyleft versions of that license
+ published by that same organization.
+
+ “Incorporate†means to publish or republish a Document, in whole or
+ in part, as part of another Document.
+
+ An MMC is “eligible for relicensing†if it is licensed under this
+ License, and if all works that were first published under this
+ License somewhere other than this MMC, and subsequently
+ incorporated in whole or in part into the MMC, (1) had no cover
+ texts or invariant sections, and (2) were thus incorporated prior
+ to November 1, 2008.
+
+ The operator of an MMC Site may republish an MMC contained in the
+ site under CC-BY-SA on the same site at any time before August 1,
+ 2009, provided the MMC is eligible for relicensing.
+
+ADDENDUM: How to use this License for your documents
+====================================================
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and license
+notices just after the title page:
+
+ Copyright (C) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+
+ If you have Invariant Sections, Front-Cover Texts and Back-Cover
+Texts, replace the “with...Texts.†line with this:
+
+ with the Invariant Sections being LIST THEIR TITLES, with
+ the Front-Cover Texts being LIST, and with the Back-Cover Texts
+ being LIST.
+
+ If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+ If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of free
+software license, such as the GNU General Public License, to permit
+their use in free software.
+
+
+File: dash.info, Node: GPL, Next: Index, Prev: FDL, Up: Top
+
+Appendix B GNU General Public License
+*************************************
+
+ Version 3, 29 June 2007
+
+ Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
+
+ Everyone is permitted to copy and distribute verbatim copies of this
+ license document, but changing it is not allowed.
+
+Preamble
+========
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program—to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers’ and authors’ protection, the GPL clearly explains
+that there is no warranty for this free software. For both users’ and
+authors’ sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users’ freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+====================
+
+ 0. Definitions.
+
+ “This License†refers to version 3 of the GNU General Public
+ License.
+
+ “Copyright†also means copyright-like laws that apply to other
+ kinds of works, such as semiconductor masks.
+
+ “The Program†refers to any copyrightable work licensed under this
+ License. Each licensee is addressed as “youâ€. “Licensees†and
+ “recipients†may be individuals or organizations.
+
+ To “modify†a work means to copy from or adapt all or part of the
+ work in a fashion requiring copyright permission, other than the
+ making of an exact copy. The resulting work is called a “modified
+ version†of the earlier work or a work “based on†the earlier work.
+
+ A “covered work†means either the unmodified Program or a work
+ based on the Program.
+
+ To “propagate†a work means to do anything with it that, without
+ permission, would make you directly or secondarily liable for
+ infringement under applicable copyright law, except executing it on
+ a computer or modifying a private copy. Propagation includes
+ copying, distribution (with or without modification), making
+ available to the public, and in some countries other activities as
+ well.
+
+ To “convey†a work means any kind of propagation that enables other
+ parties to make or receive copies. Mere interaction with a user
+ through a computer network, with no transfer of a copy, is not
+ conveying.
+
+ An interactive user interface displays “Appropriate Legal Noticesâ€
+ to the extent that it includes a convenient and prominently visible
+ feature that (1) displays an appropriate copyright notice, and (2)
+ tells the user that there is no warranty for the work (except to
+ the extent that warranties are provided), that licensees may convey
+ the work under this License, and how to view a copy of this
+ License. If the interface presents a list of user commands or
+ options, such as a menu, a prominent item in the list meets this
+ criterion.
+
+ 1. Source Code.
+
+ The “source code†for a work means the preferred form of the work
+ for making modifications to it. “Object code†means any non-source
+ form of a work.
+
+ A “Standard Interface†means an interface that either is an
+ official standard defined by a recognized standards body, or, in
+ the case of interfaces specified for a particular programming
+ language, one that is widely used among developers working in that
+ language.
+
+ The “System Libraries†of an executable work include anything,
+ other than the work as a whole, that (a) is included in the normal
+ form of packaging a Major Component, but which is not part of that
+ Major Component, and (b) serves only to enable use of the work with
+ that Major Component, or to implement a Standard Interface for
+ which an implementation is available to the public in source code
+ form. A “Major Componentâ€, in this context, means a major
+ essential component (kernel, window system, and so on) of the
+ specific operating system (if any) on which the executable work
+ runs, or a compiler used to produce the work, or an object code
+ interpreter used to run it.
+
+ The “Corresponding Source†for a work in object code form means all
+ the source code needed to generate, install, and (for an executable
+ work) run the object code and to modify the work, including scripts
+ to control those activities. However, it does not include the
+ work’s System Libraries, or general-purpose tools or generally
+ available free programs which are used unmodified in performing
+ those activities but which are not part of the work. For example,
+ Corresponding Source includes interface definition files associated
+ with source files for the work, and the source code for shared
+ libraries and dynamically linked subprograms that the work is
+ specifically designed to require, such as by intimate data
+ communication or control flow between those subprograms and other
+ parts of the work.
+
+ The Corresponding Source need not include anything that users can
+ regenerate automatically from other parts of the Corresponding
+ Source.
+
+ The Corresponding Source for a work in source code form is that
+ same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+ copyright on the Program, and are irrevocable provided the stated
+ conditions are met. This License explicitly affirms your unlimited
+ permission to run the unmodified Program. The output from running
+ a covered work is covered by this License only if the output, given
+ its content, constitutes a covered work. This License acknowledges
+ your rights of fair use or other equivalent, as provided by
+ copyright law.
+
+ You may make, run and propagate covered works that you do not
+ convey, without conditions so long as your license otherwise
+ remains in force. You may convey covered works to others for the
+ sole purpose of having them make modifications exclusively for you,
+ or provide you with facilities for running those works, provided
+ that you comply with the terms of this License in conveying all
+ material for which you do not control copyright. Those thus making
+ or running the covered works for you must do so exclusively on your
+ behalf, under your direction and control, on terms that prohibit
+ them from making any copies of your copyrighted material outside
+ their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+ the conditions stated below. Sublicensing is not allowed; section
+ 10 makes it unnecessary.
+
+ 3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+ measure under any applicable law fulfilling obligations under
+ article 11 of the WIPO copyright treaty adopted on 20 December
+ 1996, or similar laws prohibiting or restricting circumvention of
+ such measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+ circumvention of technological measures to the extent such
+ circumvention is effected by exercising rights under this License
+ with respect to the covered work, and you disclaim any intention to
+ limit operation or modification of the work as a means of
+ enforcing, against the work’s users, your or third parties’ legal
+ rights to forbid circumvention of technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program’s source code as you
+ receive it, in any medium, provided that you conspicuously and
+ appropriately publish on each copy an appropriate copyright notice;
+ keep intact all notices stating that this License and any
+ non-permissive terms added in accord with section 7 apply to the
+ code; keep intact all notices of the absence of any warranty; and
+ give all recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+ and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+ produce it from the Program, in the form of source code under the
+ terms of section 4, provided that you also meet all of these
+ conditions:
+
+ a. The work must carry prominent notices stating that you
+ modified it, and giving a relevant date.
+
+ b. The work must carry prominent notices stating that it is
+ released under this License and any conditions added under
+ section 7. This requirement modifies the requirement in
+ section 4 to “keep intact all noticesâ€.
+
+ c. You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable
+ section 7 additional terms, to the whole of the work, and all
+ its parts, regardless of how they are packaged. This License
+ gives no permission to license the work in any other way, but
+ it does not invalidate such permission if you have separately
+ received it.
+
+ d. If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has
+ interactive interfaces that do not display Appropriate Legal
+ Notices, your work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+ works, which are not by their nature extensions of the covered
+ work, and which are not combined with it such as to form a larger
+ program, in or on a volume of a storage or distribution medium, is
+ called an “aggregate†if the compilation and its resulting
+ copyright are not used to limit the access or legal rights of the
+ compilation’s users beyond what the individual works permit.
+ Inclusion of a covered work in an aggregate does not cause this
+ License to apply to the other parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+ of sections 4 and 5, provided that you also convey the
+ machine-readable Corresponding Source under the terms of this
+ License, in one of these ways:
+
+ a. Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b. Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that
+ product model, to give anyone who possesses the object code
+ either (1) a copy of the Corresponding Source for all the
+ software in the product that is covered by this License, on a
+ durable physical medium customarily used for software
+ interchange, for a price no more than your reasonable cost of
+ physically performing this conveying of source, or (2) access
+ to copy the Corresponding Source from a network server at no
+ charge.
+
+ c. Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially,
+ and only if you received the object code with such an offer,
+ in accord with subsection 6b.
+
+ d. Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to
+ the Corresponding Source in the same way through the same
+ place at no further charge. You need not require recipients
+ to copy the Corresponding Source along with the object code.
+ If the place to copy the object code is a network server, the
+ Corresponding Source may be on a different server (operated by
+ you or a third party) that supports equivalent copying
+ facilities, provided you maintain clear directions next to the
+ object code saying where to find the Corresponding Source.
+ Regardless of what server hosts the Corresponding Source, you
+ remain obligated to ensure that it is available for as long as
+ needed to satisfy these requirements.
+
+ e. Convey the object code using peer-to-peer transmission,
+ provided you inform other peers where the object code and
+ Corresponding Source of the work are being offered to the
+ general public at no charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is
+ excluded from the Corresponding Source as a System Library, need
+ not be included in conveying the object code work.
+
+ A “User Product†is either (1) a “consumer productâ€, which means
+ any tangible personal property which is normally used for personal,
+ family, or household purposes, or (2) anything designed or sold for
+ incorporation into a dwelling. In determining whether a product is
+ a consumer product, doubtful cases shall be resolved in favor of
+ coverage. For a particular product received by a particular user,
+ “normally used†refers to a typical or common use of that class of
+ product, regardless of the status of the particular user or of the
+ way in which the particular user actually uses, or expects or is
+ expected to use, the product. A product is a consumer product
+ regardless of whether the product has substantial commercial,
+ industrial or non-consumer uses, unless such uses represent the
+ only significant mode of use of the product.
+
+ “Installation Information†for a User Product means any methods,
+ procedures, authorization keys, or other information required to
+ install and execute modified versions of a covered work in that
+ User Product from a modified version of its Corresponding Source.
+ The information must suffice to ensure that the continued
+ functioning of the modified object code is in no case prevented or
+ interfered with solely because modification has been made.
+
+ If you convey an object code work under this section in, or with,
+ or specifically for use in, a User Product, and the conveying
+ occurs as part of a transaction in which the right of possession
+ and use of the User Product is transferred to the recipient in
+ perpetuity or for a fixed term (regardless of how the transaction
+ is characterized), the Corresponding Source conveyed under this
+ section must be accompanied by the Installation Information. But
+ this requirement does not apply if neither you nor any third party
+ retains the ability to install modified object code on the User
+ Product (for example, the work has been installed in ROM).
+
+ The requirement to provide Installation Information does not
+ include a requirement to continue to provide support service,
+ warranty, or updates for a work that has been modified or installed
+ by the recipient, or for the User Product in which it has been
+ modified or installed. Access to a network may be denied when the
+ modification itself materially and adversely affects the operation
+ of the network or violates the rules and protocols for
+ communication across the network.
+
+ Corresponding Source conveyed, and Installation Information
+ provided, in accord with this section must be in a format that is
+ publicly documented (and with an implementation available to the
+ public in source code form), and must require no special password
+ or key for unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ “Additional permissions†are terms that supplement the terms of
+ this License by making exceptions from one or more of its
+ conditions. Additional permissions that are applicable to the
+ entire Program shall be treated as though they were included in
+ this License, to the extent that they are valid under applicable
+ law. If additional permissions apply only to part of the Program,
+ that part may be used separately under those permissions, but the
+ entire Program remains governed by this License without regard to
+ the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+ remove any additional permissions from that copy, or from any part
+ of it. (Additional permissions may be written to require their own
+ removal in certain cases when you modify the work.) You may place
+ additional permissions on material, added by you to a covered work,
+ for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material
+ you add to a covered work, you may (if authorized by the copyright
+ holders of that material) supplement the terms of this License with
+ terms:
+
+ a. Disclaiming warranty or limiting liability differently from
+ the terms of sections 15 and 16 of this License; or
+
+ b. Requiring preservation of specified reasonable legal notices
+ or author attributions in that material or in the Appropriate
+ Legal Notices displayed by works containing it; or
+
+ c. Prohibiting misrepresentation of the origin of that material,
+ or requiring that modified versions of such material be marked
+ in reasonable ways as different from the original version; or
+
+ d. Limiting the use for publicity purposes of names of licensors
+ or authors of the material; or
+
+ e. Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f. Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified
+ versions of it) with contractual assumptions of liability to
+ the recipient, for any liability that these contractual
+ assumptions directly impose on those licensors and authors.
+
+ All other non-permissive additional terms are considered “further
+ restrictions†within the meaning of section 10. If the Program as
+ you received it, or any part of it, contains a notice stating that
+ it is governed by this License along with a term that is a further
+ restriction, you may remove that term. If a license document
+ contains a further restriction but permits relicensing or conveying
+ under this License, you may add to a covered work material governed
+ by the terms of that license document, provided that the further
+ restriction does not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+ must place, in the relevant source files, a statement of the
+ additional terms that apply to those files, or a notice indicating
+ where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in
+ the form of a separately written license, or stated as exceptions;
+ the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+ provided under this License. Any attempt otherwise to propagate or
+ modify it is void, and will automatically terminate your rights
+ under this License (including any patent licenses granted under the
+ third paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly and
+ finally terminates your license, and (b) permanently, if the
+ copyright holder fails to notify you of the violation by some
+ reasonable means prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you have
+ received notice of violation of this License (for any work) from
+ that copyright holder, and you cure the violation prior to 30 days
+ after your receipt of the notice.
+
+ Termination of your rights under this section does not terminate
+ the licenses of parties who have received copies or rights from you
+ under this License. If your rights have been terminated and not
+ permanently reinstated, you do not qualify to receive new licenses
+ for the same material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+ run a copy of the Program. Ancillary propagation of a covered work
+ occurring solely as a consequence of using peer-to-peer
+ transmission to receive a copy likewise does not require
+ acceptance. However, nothing other than this License grants you
+ permission to propagate or modify any covered work. These actions
+ infringe copyright if you do not accept this License. Therefore,
+ by modifying or propagating a covered work, you indicate your
+ acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+ receives a license from the original licensors, to run, modify and
+ propagate that work, subject to this License. You are not
+ responsible for enforcing compliance by third parties with this
+ License.
+
+ An “entity transaction†is a transaction transferring control of an
+ organization, or substantially all assets of one, or subdividing an
+ organization, or merging organizations. If propagation of a
+ covered work results from an entity transaction, each party to that
+ transaction who receives a copy of the work also receives whatever
+ licenses to the work the party’s predecessor in interest had or
+ could give under the previous paragraph, plus a right to possession
+ of the Corresponding Source of the work from the predecessor in
+ interest, if the predecessor has it or can get it with reasonable
+ efforts.
+
+ You may not impose any further restrictions on the exercise of the
+ rights granted or affirmed under this License. For example, you
+ may not impose a license fee, royalty, or other charge for exercise
+ of rights granted under this License, and you may not initiate
+ litigation (including a cross-claim or counterclaim in a lawsuit)
+ alleging that any patent claim is infringed by making, using,
+ selling, offering for sale, or importing the Program or any portion
+ of it.
+
+ 11. Patents.
+
+ A “contributor†is a copyright holder who authorizes use under this
+ License of the Program or a work on which the Program is based.
+ The work thus licensed is called the contributor’s “contributor
+ versionâ€.
+
+ A contributor’s “essential patent claims†are all patent claims
+ owned or controlled by the contributor, whether already acquired or
+ hereafter acquired, that would be infringed by some manner,
+ permitted by this License, of making, using, or selling its
+ contributor version, but do not include claims that would be
+ infringed only as a consequence of further modification of the
+ contributor version. For purposes of this definition, “controlâ€
+ includes the right to grant patent sublicenses in a manner
+ consistent with the requirements of this License.
+
+ Each contributor grants you a non-exclusive, worldwide,
+ royalty-free patent license under the contributor’s essential
+ patent claims, to make, use, sell, offer for sale, import and
+ otherwise run, modify and propagate the contents of its contributor
+ version.
+
+ In the following three paragraphs, a “patent license†is any
+ express agreement or commitment, however denominated, not to
+ enforce a patent (such as an express permission to practice a
+ patent or covenant not to sue for patent infringement). To “grantâ€
+ such a patent license to a party means to make such an agreement or
+ commitment not to enforce a patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent
+ license, and the Corresponding Source of the work is not available
+ for anyone to copy, free of charge and under the terms of this
+ License, through a publicly available network server or other
+ readily accessible means, then you must either (1) cause the
+ Corresponding Source to be so available, or (2) arrange to deprive
+ yourself of the benefit of the patent license for this particular
+ work, or (3) arrange, in a manner consistent with the requirements
+ of this License, to extend the patent license to downstream
+ recipients. “Knowingly relying†means you have actual knowledge
+ that, but for the patent license, your conveying the covered work
+ in a country, or your recipient’s use of the covered work in a
+ country, would infringe one or more identifiable patents in that
+ country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+ arrangement, you convey, or propagate by procuring conveyance of, a
+ covered work, and grant a patent license to some of the parties
+ receiving the covered work authorizing them to use, propagate,
+ modify or convey a specific copy of the covered work, then the
+ patent license you grant is automatically extended to all
+ recipients of the covered work and works based on it.
+
+ A patent license is “discriminatory†if it does not include within
+ the scope of its coverage, prohibits the exercise of, or is
+ conditioned on the non-exercise of one or more of the rights that
+ are specifically granted under this License. You may not convey a
+ covered work if you are a party to an arrangement with a third
+ party that is in the business of distributing software, under which
+ you make payment to the third party based on the extent of your
+ activity of conveying the work, and under which the third party
+ grants, to any of the parties who would receive the covered work
+ from you, a discriminatory patent license (a) in connection with
+ copies of the covered work conveyed by you (or copies made from
+ those copies), or (b) primarily for and in connection with specific
+ products or compilations that contain the covered work, unless you
+ entered into that arrangement, or that patent license was granted,
+ prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+ any implied license or other defenses to infringement that may
+ otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others’ Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement
+ or otherwise) that contradict the conditions of this License, they
+ do not excuse you from the conditions of this License. If you
+ cannot convey a covered work so as to satisfy simultaneously your
+ obligations under this License and any other pertinent obligations,
+ then as a consequence you may not convey it at all. For example,
+ if you agree to terms that obligate you to collect a royalty for
+ further conveying from those to whom you convey the Program, the
+ only way you could satisfy both those terms and this License would
+ be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+ permission to link or combine any covered work with a work licensed
+ under version 3 of the GNU Affero General Public License into a
+ single combined work, and to convey the resulting work. The terms
+ of this License will continue to apply to the part which is the
+ covered work, but the special requirements of the GNU Affero
+ General Public License, section 13, concerning interaction through
+ a network will apply to the combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new
+ versions of the GNU General Public License from time to time. Such
+ new versions will be similar in spirit to the present version, but
+ may differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+ Program specifies that a certain numbered version of the GNU
+ General Public License “or any later version†applies to it, you
+ have the option of following the terms and conditions either of
+ that numbered version or of any later version published by the Free
+ Software Foundation. If the Program does not specify a version
+ number of the GNU General Public License, you may choose any
+ version ever published by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+ versions of the GNU General Public License can be used, that
+ proxy’s public statement of acceptance of a version permanently
+ authorizes you to choose that version for the Program.
+
+ Later license versions may give you additional or different
+ permissions. However, no additional obligations are imposed on any
+ author or copyright holder as a result of your choosing to follow a
+ later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+ COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS ISâ€
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE
+ RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
+ SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
+ AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+ THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+ BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+ above cannot be given local legal effect according to their terms,
+ reviewing courts shall apply local law that most closely
+ approximates an absolute waiver of all civil liability in
+ connection with the Program, unless a warranty or assumption of
+ liability accompanies a copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+===========================
+
+How to Apply These Terms to Your New Programs
+=============================================
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least the
+“copyright†line and a pointer to where the full notice is found.
+
+ ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
+ Copyright (C) YEAR NAME OF AUTHOR
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ Also add information on how to contact you by electronic and paper
+mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ PROGRAM Copyright (C) YEAR NAME OF AUTHOR
+ This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type ‘show c’ for details.
+
+ The hypothetical commands ‘show w’ and ‘show c’ should show the
+appropriate parts of the General Public License. Of course, your
+program’s commands might be different; for a GUI interface, you would
+use an “about boxâ€.
+
+ You should also get your employer (if you work as a programmer) or
+school, if any, to sign a “copyright disclaimer†for the program, if
+necessary. For more information on this, and how to apply and follow
+the GNU GPL, see <https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your
+program into proprietary programs. If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library. If this is what you want to do, use the
+GNU Lesser General Public License instead of this License. But first,
+please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
+
+
+File: dash.info, Node: Index, Prev: GPL, Up: Top
+
+Index
+*****
+
+
+* Menu:
+
+* !cdr: Destructive operations.
+ (line 16)
+* !cons: Destructive operations.
+ (line 8)
+* -->: Threading macros. (line 35)
+* ->: Threading macros. (line 9)
+* ->>: Threading macros. (line 22)
+* -all?: Predicates. (line 53)
+* -andfn: Function combinators.
+ (line 184)
+* -annotate: Maps. (line 84)
+* -any?: Predicates. (line 41)
+* -applify: Function combinators.
+ (line 63)
+* -as->: Threading macros. (line 49)
+* -butlast: Other list operations.
+ (line 335)
+* -clone: Tree operations. (line 122)
+* -common-prefix: Reductions. (line 242)
+* -common-suffix: Reductions. (line 252)
+* -compose: Function combinators.
+ (line 49)
+* -concat: List to list. (line 23)
+* -cons*: Other list operations.
+ (line 30)
+* -cons-pair?: Predicates. (line 167)
+* -const: Function combinators.
+ (line 128)
+* -contains?: Predicates. (line 100)
+* -copy: Maps. (line 139)
+* -count: Reductions. (line 172)
+* -cut: Function combinators.
+ (line 140)
+* -cycle: Other list operations.
+ (line 180)
+* -difference: Set operations. (line 20)
+* -distinct: Set operations. (line 62)
+* -dotimes: Side effects. (line 80)
+* -doto: Threading macros. (line 99)
+* -drop: Sublist selection. (line 147)
+* -drop-last: Sublist selection. (line 161)
+* -drop-while: Sublist selection. (line 192)
+* -each: Side effects. (line 8)
+* -each-indexed: Side effects. (line 38)
+* -each-r: Side effects. (line 52)
+* -each-r-while: Side effects. (line 65)
+* -each-while: Side effects. (line 24)
+* -elem-index: Indexing. (line 9)
+* -elem-indices: Indexing. (line 21)
+* -every: Predicates. (line 23)
+* -fifth-item: Other list operations.
+ (line 315)
+* -filter: Sublist selection. (line 8)
+* -find-index: Indexing. (line 32)
+* -find-indices: Indexing. (line 60)
+* -find-last-index: Indexing. (line 46)
+* -first: Other list operations.
+ (line 246)
+* -first-item: Other list operations.
+ (line 272)
+* -fix: Other list operations.
+ (line 375)
+* -fixfn: Function combinators.
+ (line 224)
+* -flatten: List to list. (line 34)
+* -flatten-n: List to list. (line 56)
+* -flip: Function combinators.
+ (line 95)
+* -fourth-item: Other list operations.
+ (line 305)
+* -grade-down: Indexing. (line 81)
+* -grade-up: Indexing. (line 71)
+* -group-by: Partitioning. (line 194)
+* -if-let: Binding. (line 34)
+* -if-let*: Binding. (line 45)
+* -inits: Reductions. (line 222)
+* -insert-at: List to list. (line 110)
+* -interleave: Other list operations.
+ (line 67)
+* -interpose: Other list operations.
+ (line 57)
+* -intersection: Set operations. (line 32)
+* -iota: Other list operations.
+ (line 78)
+* -is-infix?: Predicates. (line 153)
+* -is-prefix?: Predicates. (line 129)
+* -is-suffix?: Predicates. (line 141)
+* -iterate: Unfolding. (line 9)
+* -iteratefn: Function combinators.
+ (line 201)
+* -juxt: Function combinators.
+ (line 37)
+* -keep: List to list. (line 8)
+* -lambda: Binding. (line 247)
+* -last: Other list operations.
+ (line 262)
+* -last-item: Other list operations.
+ (line 325)
+* -let: Binding. (line 61)
+* -let*: Binding. (line 227)
+* -list: Other list operations.
+ (line 358)
+* -map: Maps. (line 10)
+* -map-first: Maps. (line 38)
+* -map-indexed: Maps. (line 66)
+* -map-last: Maps. (line 52)
+* -map-when: Maps. (line 22)
+* -mapcat: Maps. (line 128)
+* -max: Reductions. (line 286)
+* -max-by: Reductions. (line 296)
+* -min: Reductions. (line 262)
+* -min-by: Reductions. (line 272)
+* -non-nil: Sublist selection. (line 94)
+* -none?: Predicates. (line 73)
+* -not: Function combinators.
+ (line 153)
+* -on: Function combinators.
+ (line 75)
+* -only-some?: Predicates. (line 85)
+* -orfn: Function combinators.
+ (line 167)
+* -pad: Other list operations.
+ (line 191)
+* -partial: Function combinators.
+ (line 8)
+* -partition: Partitioning. (line 80)
+* -partition-after-item: Partitioning. (line 184)
+* -partition-after-pred: Partitioning. (line 151)
+* -partition-all: Partitioning. (line 92)
+* -partition-all-in-steps: Partitioning. (line 115)
+* -partition-before-item: Partitioning. (line 174)
+* -partition-before-pred: Partitioning. (line 163)
+* -partition-by: Partitioning. (line 127)
+* -partition-by-header: Partitioning. (line 138)
+* -partition-in-steps: Partitioning. (line 103)
+* -permutations: Set operations. (line 52)
+* -powerset: Set operations. (line 44)
+* -prodfn: Function combinators.
+ (line 258)
+* -product: Reductions. (line 201)
+* -reduce: Reductions. (line 53)
+* -reduce-from: Reductions. (line 8)
+* -reduce-r: Reductions. (line 72)
+* -reduce-r-from: Reductions. (line 26)
+* -reductions: Reductions. (line 136)
+* -reductions-from: Reductions. (line 100)
+* -reductions-r: Reductions. (line 154)
+* -reductions-r-from: Reductions. (line 118)
+* -remove: Sublist selection. (line 26)
+* -remove-at: List to list. (line 146)
+* -remove-at-indices: List to list. (line 159)
+* -remove-first: Sublist selection. (line 43)
+* -remove-item: Sublist selection. (line 83)
+* -remove-last: Sublist selection. (line 64)
+* -repeat: Other list operations.
+ (line 19)
+* -replace: List to list. (line 68)
+* -replace-at: List to list. (line 121)
+* -replace-first: List to list. (line 82)
+* -replace-last: List to list. (line 96)
+* -rotate: Other list operations.
+ (line 8)
+* -rotate-args: Function combinators.
+ (line 112)
+* -rpartial: Function combinators.
+ (line 22)
+* -running-product: Reductions. (line 211)
+* -running-sum: Reductions. (line 190)
+* -same-items?: Predicates. (line 115)
+* -second-item: Other list operations.
+ (line 285)
+* -select-by-indices: Sublist selection. (line 208)
+* -select-column: Sublist selection. (line 238)
+* -select-columns: Sublist selection. (line 219)
+* -separate: Partitioning. (line 69)
+* -setq: Binding. (line 270)
+* -slice: Sublist selection. (line 104)
+* -snoc: Other list operations.
+ (line 43)
+* -some: Predicates. (line 8)
+* -some-->: Threading macros. (line 86)
+* -some->: Threading macros. (line 62)
+* -some->>: Threading macros. (line 74)
+* -sort: Other list operations.
+ (line 345)
+* -splice: Maps. (line 95)
+* -splice-list: Maps. (line 115)
+* -split-at: Partitioning. (line 8)
+* -split-on: Partitioning. (line 34)
+* -split-when: Partitioning. (line 52)
+* -split-with: Partitioning. (line 23)
+* -sum: Reductions. (line 180)
+* -table: Other list operations.
+ (line 202)
+* -table-flat: Other list operations.
+ (line 221)
+* -tails: Reductions. (line 232)
+* -take: Sublist selection. (line 120)
+* -take-last: Sublist selection. (line 133)
+* -take-while: Sublist selection. (line 175)
+* -third-item: Other list operations.
+ (line 295)
+* -tree-map: Tree operations. (line 28)
+* -tree-map-nodes: Tree operations. (line 39)
+* -tree-mapreduce: Tree operations. (line 84)
+* -tree-mapreduce-from: Tree operations. (line 103)
+* -tree-reduce: Tree operations. (line 52)
+* -tree-reduce-from: Tree operations. (line 69)
+* -tree-seq: Tree operations. (line 8)
+* -unfold: Unfolding. (line 25)
+* -union: Set operations. (line 8)
+* -unzip: Other list operations.
+ (line 158)
+* -update-at: List to list. (line 133)
+* -when-let: Binding. (line 9)
+* -when-let*: Binding. (line 21)
+* -zip: Other list operations.
+ (line 107)
+* -zip-fill: Other list operations.
+ (line 150)
+* -zip-lists: Other list operations.
+ (line 131)
+* -zip-with: Other list operations.
+ (line 91)
+* dash-fontify-mode: Fontification of special variables.
+ (line 6)
+* dash-register-info-lookup: Info symbol lookup. (line 6)
+* global-dash-fontify-mode: Fontification of special variables.
+ (line 12)
+
+
+
+Tag Table:
+Node: Top742
+Node: Installation2397
+Node: Using in a package3159
+Node: Fontification of special variables3504
+Node: Info symbol lookup4294
+Node: Functions4877
+Node: Maps6361
+Ref: -map6658
+Ref: -map-when7031
+Ref: -map-first7606
+Ref: -map-last8081
+Ref: -map-indexed8551
+Ref: -annotate9237
+Ref: -splice9724
+Ref: -splice-list10502
+Ref: -mapcat10961
+Ref: -copy11334
+Node: Sublist selection11522
+Ref: -filter11715
+Ref: -remove12262
+Ref: -remove-first12800
+Ref: -remove-last13642
+Ref: -remove-item14367
+Ref: -non-nil14767
+Ref: -slice15043
+Ref: -take15572
+Ref: -take-last15979
+Ref: -drop16410
+Ref: -drop-last16851
+Ref: -take-while17277
+Ref: -drop-while17892
+Ref: -select-by-indices18508
+Ref: -select-columns19019
+Ref: -select-column19722
+Node: List to list20185
+Ref: -keep20377
+Ref: -concat20941
+Ref: -flatten21235
+Ref: -flatten-n21991
+Ref: -replace22375
+Ref: -replace-first22836
+Ref: -replace-last23331
+Ref: -insert-at23819
+Ref: -replace-at24144
+Ref: -update-at24531
+Ref: -remove-at25019
+Ref: -remove-at-indices25504
+Node: Reductions26083
+Ref: -reduce-from26279
+Ref: -reduce-r-from27003
+Ref: -reduce28266
+Ref: -reduce-r29017
+Ref: -reductions-from30295
+Ref: -reductions-r-from31101
+Ref: -reductions31931
+Ref: -reductions-r32642
+Ref: -count33387
+Ref: -sum33611
+Ref: -running-sum33799
+Ref: -product34120
+Ref: -running-product34328
+Ref: -inits34669
+Ref: -tails34914
+Ref: -common-prefix35158
+Ref: -common-suffix35452
+Ref: -min35746
+Ref: -min-by35972
+Ref: -max36493
+Ref: -max-by36718
+Node: Unfolding37244
+Ref: -iterate37485
+Ref: -unfold37932
+Node: Predicates38737
+Ref: -some38914
+Ref: -every39331
+Ref: -any?40010
+Ref: -all?40341
+Ref: -none?41048
+Ref: -only-some?41350
+Ref: -contains?41835
+Ref: -same-items?42224
+Ref: -is-prefix?42609
+Ref: -is-suffix?42935
+Ref: -is-infix?43261
+Ref: -cons-pair?43615
+Node: Partitioning43940
+Ref: -split-at44128
+Ref: -split-with44792
+Ref: -split-on45192
+Ref: -split-when45863
+Ref: -separate46500
+Ref: -partition46939
+Ref: -partition-all47388
+Ref: -partition-in-steps47813
+Ref: -partition-all-in-steps48307
+Ref: -partition-by48789
+Ref: -partition-by-header49167
+Ref: -partition-after-pred49768
+Ref: -partition-before-pred50215
+Ref: -partition-before-item50600
+Ref: -partition-after-item50907
+Ref: -group-by51209
+Node: Indexing51642
+Ref: -elem-index51844
+Ref: -elem-indices52239
+Ref: -find-index52619
+Ref: -find-last-index53108
+Ref: -find-indices53612
+Ref: -grade-up54017
+Ref: -grade-down54424
+Node: Set operations54838
+Ref: -union55021
+Ref: -difference55459
+Ref: -intersection55871
+Ref: -powerset56303
+Ref: -permutations56513
+Ref: -distinct56809
+Node: Other list operations57183
+Ref: -rotate57408
+Ref: -repeat57761
+Ref: -cons*58040
+Ref: -snoc58456
+Ref: -interpose58866
+Ref: -interleave59160
+Ref: -iota59526
+Ref: -zip-with60009
+Ref: -zip60723
+Ref: -zip-lists61552
+Ref: -zip-fill62250
+Ref: -unzip62572
+Ref: -cycle63314
+Ref: -pad63713
+Ref: -table64032
+Ref: -table-flat64818
+Ref: -first65823
+Ref: -last66309
+Ref: -first-item66643
+Ref: -second-item67042
+Ref: -third-item67306
+Ref: -fourth-item67568
+Ref: -fifth-item67834
+Ref: -last-item68096
+Ref: -butlast68387
+Ref: -sort68632
+Ref: -list69118
+Ref: -fix69687
+Node: Tree operations70176
+Ref: -tree-seq70372
+Ref: -tree-map71227
+Ref: -tree-map-nodes71667
+Ref: -tree-reduce72514
+Ref: -tree-reduce-from73396
+Ref: -tree-mapreduce73996
+Ref: -tree-mapreduce-from74855
+Ref: -clone76140
+Node: Threading macros76467
+Ref: ->76692
+Ref: ->>77180
+Ref: -->77683
+Ref: -as->78239
+Ref: -some->78693
+Ref: -some->>79066
+Ref: -some-->79501
+Ref: -doto80050
+Node: Binding80603
+Ref: -when-let80810
+Ref: -when-let*81265
+Ref: -if-let81788
+Ref: -if-let*82148
+Ref: -let82765
+Ref: -let*88837
+Ref: -lambda89774
+Ref: -setq90580
+Node: Side effects91381
+Ref: -each91575
+Ref: -each-while92096
+Ref: -each-indexed92698
+Ref: -each-r93284
+Ref: -each-r-while93720
+Ref: -dotimes94346
+Node: Destructive operations94899
+Ref: !cons95117
+Ref: !cdr95321
+Node: Function combinators95514
+Ref: -partial95718
+Ref: -rpartial96236
+Ref: -juxt96884
+Ref: -compose97336
+Ref: -applify97943
+Ref: -on98373
+Ref: -flip99145
+Ref: -rotate-args99669
+Ref: -const100298
+Ref: -cut100640
+Ref: -not101120
+Ref: -orfn101646
+Ref: -andfn102408
+Ref: -iteratefn103164
+Ref: -fixfn103866
+Ref: -prodfn105422
+Node: Development106480
+Node: Contribute106769
+Node: Contributors107781
+Node: FDL109874
+Node: GPL135194
+Node: Index172943
+
+End Tag Table
+
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/emacs.d/elpa/dash-20210708.2009/dir b/emacs.d/elpa/dash-20210708.2009/dir
new file mode 100644
index 0000000..7d473f4
--- /dev/null
+++ b/emacs.d/elpa/dash-20210708.2009/dir
@@ -0,0 +1,18 @@
+This is the file .../info/dir, which contains the
+topmost node of the Info hierarchy, called (dir)Top.
+The first time you invoke Info you start off looking at this node.
+
+File: dir, Node: Top This is the top of the INFO tree
+
+ This (the Directory node) gives a menu of major topics.
+ Typing "q" exits, "H" lists all Info commands, "d" returns here,
+ "h" gives a primer for first-timers,
+ "mEmacs<Return>" visits the Emacs manual, etc.
+
+ In Emacs, you can click mouse button 2 on a menu item or cross reference
+ to select it.
+
+* Menu:
+
+Emacs
+* Dash: (dash.info). A modern list library for GNU Emacs.
diff --git a/emacs.d/elpa/ht-20210119.741/ht-autoloads.el b/emacs.d/elpa/ht-20210119.741/ht-autoloads.el
new file mode 100644
index 0000000..c860d46
--- /dev/null
+++ b/emacs.d/elpa/ht-20210119.741/ht-autoloads.el
@@ -0,0 +1,22 @@
+;;; ht-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "ht" "ht.el" (0 0 0 0))
+;;; Generated autoloads from ht.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ht" 'nil))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; ht-autoloads.el ends here
diff --git a/emacs.d/elpa/ht-20210119.741/ht-pkg.el b/emacs.d/elpa/ht-20210119.741/ht-pkg.el
new file mode 100644
index 0000000..15125c7
--- /dev/null
+++ b/emacs.d/elpa/ht-20210119.741/ht-pkg.el
@@ -0,0 +1,2 @@
+;;; Generated package description from ht-20210119.741/ht.el -*- no-byte-compile: t -*-
+(define-package "ht" "20210119.741" "The missing hash table library for Emacs" '((dash "2.12.0")) :commit "c4c1be487d6ecb353d07881526db05d7fc90ea87" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("hash table" "hash map" "hash"))
diff --git a/emacs.d/elpa/ht-20210119.741/ht.el b/emacs.d/elpa/ht-20210119.741/ht.el
new file mode 100644
index 0000000..0809ef1
--- /dev/null
+++ b/emacs.d/elpa/ht-20210119.741/ht.el
@@ -0,0 +1,337 @@
+;;; ht.el --- The missing hash table library for Emacs -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2013 Wilfred Hughes
+
+;; Author: Wilfred Hughes <me@wilfred.me.uk>
+;; Version: 2.4
+;; Package-Version: 20210119.741
+;; Package-Commit: c4c1be487d6ecb353d07881526db05d7fc90ea87
+;; Keywords: hash table, hash map, hash
+;; Package-Requires: ((dash "2.12.0"))
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The missing hash table library for Emacs.
+;;
+;; See documentation at https://github.com/Wilfred/ht.el
+
+;;; Code:
+
+(require 'dash)
+(require 'gv)
+(eval-when-compile
+ (require 'inline))
+
+(defmacro ht (&rest pairs)
+ "Create a hash table with the key-value pairs given.
+Keys are compared with `equal'.
+
+\(fn (KEY-1 VALUE-1) (KEY-2 VALUE-2) ...)"
+ (let* ((table-symbol (make-symbol "ht-temp"))
+ (assignments
+ (mapcar
+ (lambda (pair) `(ht-set! ,table-symbol ,@pair))
+ pairs)))
+ `(let ((,table-symbol (ht-create)))
+ ,@assignments
+ ,table-symbol)))
+
+(define-inline ht-set! (table key value)
+ "Associate KEY in TABLE with VALUE."
+ (inline-quote
+ (prog1 nil
+ (puthash ,key ,value ,table))))
+
+(defalias 'ht-set 'ht-set!)
+
+(define-inline ht-create (&optional test)
+ "Create an empty hash table.
+
+TEST indicates the function used to compare the hash
+keys. Default is `equal'. It can be `eq', `eql', `equal' or a
+user-supplied test created via `define-hash-table-test'."
+ (declare (side-effect-free t))
+ (inline-quote (make-hash-table :test (or ,test 'equal))))
+
+(defun ht<-alist (alist &optional test)
+ "Create a hash table with initial values according to ALIST.
+
+TEST indicates the function used to compare the hash
+keys. Default is `equal'. It can be `eq', `eql', `equal' or a
+user-supplied test created via `define-hash-table-test'."
+ (declare (side-effect-free t))
+ (let ((h (ht-create test)))
+ ;; the first key-value pair in an alist gets precedence, so we
+ ;; start from the end of the list:
+ (dolist (pair (reverse alist) h)
+ (let ((key (car pair))
+ (value (cdr pair)))
+ (ht-set! h key value)))))
+
+(defalias 'ht-from-alist 'ht<-alist)
+
+(defun ht<-plist (plist &optional test)
+ "Create a hash table with initial values according to PLIST.
+
+TEST indicates the function used to compare the hash
+keys. Default is `equal'. It can be `eq', `eql', `equal' or a
+user-supplied test created via `define-hash-table-test'."
+ (declare (side-effect-free t))
+ (let ((h (ht-create test)))
+ (dolist (pair (nreverse (-partition 2 plist)) h)
+ (let ((key (car pair))
+ (value (cadr pair)))
+ (ht-set! h key value)))))
+
+(defalias 'ht-from-plist 'ht<-plist)
+
+(define-inline ht-get (table key &optional default)
+ "Look up KEY in TABLE, and return the matching value.
+If KEY isn't present, return DEFAULT (nil if not specified)."
+ (declare (side-effect-free t))
+ (inline-quote
+ (gethash ,key ,table ,default)))
+
+;; Don't use `ht-set!' here, gv setter was assumed to return the value
+;; to be set.
+(gv-define-setter ht-get (value table key) `(puthash ,key ,value ,table))
+
+(define-inline ht-get* (table &rest keys)
+ "Look up KEYS in nested hash tables, starting with TABLE.
+The lookup for each key should return another hash table, except
+for the final key, which may return any value."
+ (declare (side-effect-free t))
+ (inline-letevals (table keys)
+ (inline-quote
+ (progn
+ (while ,keys
+ (setf ,table (ht-get ,table (pop ,keys))))
+ ,table))))
+
+(put 'ht-get* 'compiler-macro
+ (lambda (_ table &rest keys)
+ (--reduce-from `(ht-get ,acc ,it) table keys)))
+
+(defun ht-update! (table from-table)
+ "Update TABLE according to every key-value pair in FROM-TABLE."
+ (maphash
+ (lambda (key value) (puthash key value table))
+ from-table)
+ nil)
+
+(defalias 'ht-update 'ht-update!)
+
+(defun ht-merge (&rest tables)
+ "Crete a new tables that includes all the key-value pairs from TABLES.
+If multiple have tables have the same key, the value in the last
+table is used."
+ (let ((merged (ht-create)))
+ (mapc (lambda (table) (ht-update! merged table)) tables)
+ merged))
+
+(define-inline ht-remove! (table key)
+ "Remove KEY from TABLE."
+ (inline-quote (remhash ,key ,table)))
+
+(defalias 'ht-remove 'ht-remove!)
+
+(define-inline ht-clear! (table)
+ "Remove all keys from TABLE."
+ (inline-quote
+ (prog1 nil
+ (clrhash ,table))))
+
+(defalias 'ht-clear 'ht-clear!)
+
+(defun ht-map (function table)
+ "Apply FUNCTION to each key-value pair of TABLE, and make a list of the results.
+FUNCTION is called with two arguments, KEY and VALUE."
+ (let (results)
+ (maphash
+ (lambda (key value)
+ (push (funcall function key value) results))
+ table)
+ results))
+
+(defmacro ht-amap (form table)
+ "Anaphoric version of `ht-map'.
+For every key-value pair in TABLE, evaluate FORM with the
+variables KEY and VALUE bound. If you don't use both of
+these variables, then use `ht-map' to avoid warnings."
+ `(ht-map (lambda (key value) ,form) ,table))
+
+(defun ht-keys (table)
+ "Return a list of all the keys in TABLE."
+ (declare (side-effect-free t))
+ (ht-map (lambda (key _value) key) table))
+
+(defun ht-values (table)
+ "Return a list of all the values in TABLE."
+ (declare (side-effect-free t))
+ (ht-map (lambda (_key value) value) table))
+
+(defun ht-items (table)
+ "Return a list of two-element lists '(key value) from TABLE."
+ (declare (side-effect-free t))
+ (ht-amap (list key value) table))
+
+(defalias 'ht-each 'maphash
+ "Apply FUNCTION to each key-value pair of TABLE.
+Returns nil, used for side-effects only.")
+
+(defmacro ht-aeach (form table)
+ "Anaphoric version of `ht-each'.
+For every key-value pair in TABLE, evaluate FORM with the
+variables key and value bound."
+ `(ht-each (lambda (key value) ,form) ,table))
+
+(defun ht-select-keys (table keys)
+ "Return a copy of TABLE with only the specified KEYS."
+ (declare (side-effect-free t))
+ (let (result)
+ (setq result (make-hash-table :test (hash-table-test table)))
+ (dolist (key keys result)
+ (if (not (equal (gethash key table 'key-not-found) 'key-not-found))
+ (puthash key (gethash key table) result)))))
+
+(defun ht->plist (table)
+ "Return a flat list '(key1 value1 key2 value2...) from TABLE.
+
+Note that hash tables are unordered, so this cannot be an exact
+inverse of `ht<-plist'. The following is not guaranteed:
+
+\(let ((data '(a b c d)))
+ (equalp data
+ (ht->plist (ht<-plist data))))"
+ (declare (side-effect-free t))
+ (apply 'append (ht-items table)))
+
+(defalias 'ht-to-plist 'ht->plist)
+
+(define-inline ht-copy (table)
+ "Return a shallow copy of TABLE (keys and values are shared)."
+ (declare (side-effect-free t))
+ (inline-quote (copy-hash-table ,table)))
+
+(defun ht->alist (table)
+ "Return a list of two-element lists '(key . value) from TABLE.
+
+Note that hash tables are unordered, so this cannot be an exact
+inverse of `ht<-alist'. The following is not guaranteed:
+
+\(let ((data '((a . b) (c . d))))
+ (equalp data
+ (ht->alist (ht<-alist data))))"
+ (declare (side-effect-free t))
+ (ht-amap (cons key value) table))
+
+(defalias 'ht-to-alist 'ht->alist)
+
+(defalias 'ht? 'hash-table-p)
+
+(defalias 'ht-p 'hash-table-p)
+
+(define-inline ht-contains? (table key)
+ "Return 't if TABLE contains KEY."
+ (declare (side-effect-free t))
+ (inline-quote
+ (let ((not-found-symbol (make-symbol "ht--not-found")))
+ (not (eq (ht-get ,table ,key not-found-symbol) not-found-symbol)))))
+
+(defalias 'ht-contains-p 'ht-contains?)
+
+(define-inline ht-size (table)
+ "Return the actual number of entries in TABLE."
+ (declare (side-effect-free t))
+ (inline-quote
+ (hash-table-count ,table)))
+
+(define-inline ht-empty? (table)
+ "Return true if the actual number of entries in TABLE is zero."
+ (declare (side-effect-free t))
+ (inline-quote
+ (zerop (ht-size ,table))))
+
+(defalias 'ht-empty-p 'ht-empty?)
+
+(defun ht-select (function table)
+ "Return a hash table containing all entries in TABLE for which
+FUNCTION returns a truthy value.
+
+FUNCTION is called with two arguments, KEY and VALUE."
+ (let ((results (ht-create)))
+ (ht-each
+ (lambda (key value)
+ (when (funcall function key value)
+ (ht-set! results key value)))
+ table)
+ results))
+
+(defun ht-reject (function table)
+ "Return a hash table containing all entries in TABLE for which
+FUNCTION returns a falsy value.
+
+FUNCTION is called with two arguments, KEY and VALUE."
+ (let ((results (ht-create)))
+ (ht-each
+ (lambda (key value)
+ (unless (funcall function key value)
+ (ht-set! results key value)))
+ table)
+ results))
+
+(defun ht-reject! (function table)
+ "Delete entries from TABLE for which FUNCTION returns a falsy value.
+
+FUNCTION is called with two arguments, KEY and VALUE."
+ (ht-each
+ (lambda (key value)
+ (when (funcall function key value)
+ (remhash key table)))
+ table)
+ nil)
+
+(defalias 'ht-delete-if 'ht-reject!)
+
+(defun ht-find (function table)
+ "Return (key, value) from TABLE for which FUNCTION returns a truthy value.
+Return nil otherwise.
+
+FUNCTION is called with two arguments, KEY and VALUE."
+ (catch 'break
+ (ht-each
+ (lambda (key value)
+ (when (funcall function key value)
+ (throw 'break (list key value))))
+ table)))
+
+(defun ht-equal? (table1 table2)
+ "Return t if TABLE1 and TABLE2 have the same keys and values.
+Does not compare equality predicates."
+ (declare (side-effect-free t))
+ (let ((keys1 (ht-keys table1))
+ (keys2 (ht-keys table2))
+ (sentinel (make-symbol "ht-sentinel")))
+ (and (equal (length keys1) (length keys2))
+ (--all?
+ (equal (ht-get table1 it)
+ (ht-get table2 it sentinel))
+ keys1))))
+
+(defalias 'ht-equal-p 'ht-equal?)
+
+(provide 'ht)
+;;; ht.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-actionscript.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-actionscript.el
new file mode 100644
index 0000000..6e368dc
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-actionscript.el
@@ -0,0 +1,134 @@
+;;; lsp-actionscript.el --- ActionScript Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Jen-Chieh Shen
+
+;; Author: Jen-Chieh Shen <jcs090218@gmail.com>
+;; Keywords: actionscript lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for ActionScript
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-actionscript nil
+ "LSP support for ActionScript."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/BowlerHatLLC/vscode-as3mxml")
+ :package-version `(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-java-path "java"
+ "Path of the java executable."
+ :group 'lsp-actionscript
+ :type 'string)
+
+(defcustom lsp-actionscript-sdk-path ""
+ "Path to supported SDK.
+See https://github.com/BowlerHatLLC/vscode-as3mxml/wiki/Choose-an-ActionScript-SDK-for-the-current-workspace-in-Visual-Studio-Code."
+ :type 'string
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-version "1.5.0"
+ "Version of ActionScript language server."
+ :type 'string
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-extension-name
+ (format "vscode-nextgenas-%s.vsix" lsp-actionscript-version)
+ "File name of the extension file from language server."
+ :type 'string
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-server-download-url
+ (format "https://github.com/BowlerHatLLC/vscode-as3mxml/releases/download/v%s/%s"
+ lsp-actionscript-version lsp-actionscript-extension-name)
+ "Automatic download url for lsp-actionscript."
+ :type 'string
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-server-store-path
+ (f-join lsp-server-install-dir "as3mxml")
+ "The path to the file in which `lsp-actionscript' will be stored."
+ :type 'file
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-actionscript-option-charset "UTF8"
+ "The charset to use by the ActionScript Language server."
+ :type 'string
+ :group 'lsp-actionscript
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defun lsp-actionscript--extension-root ()
+ "The path that the downloaded extension will extract to."
+ (f-join lsp-actionscript-server-store-path
+ (format "vscode-nextgenas-%s" lsp-actionscript-version)))
+
+(defun lsp-actionscript--extension-path ()
+ "Return full path of the downloaded extension."
+ (f-join lsp-actionscript-server-store-path lsp-actionscript-extension-name))
+
+(defun lsp-actionscript--extension-dir ()
+ "Return as3mxml extension path."
+ (f-join (lsp-actionscript--extension-root) "extension"))
+
+(defun lsp-actionscript--server-command ()
+ "Startup command for ActionScript language server."
+ (list lsp-actionscript-java-path
+ (format "-Droyalelib=%s" lsp-actionscript-sdk-path)
+ (format "-Dfile.encoding=%s" lsp-actionscript-option-charset)
+ "-cp"
+ (format "%s/bundled-compiler/*;%s/bin/*"
+ (lsp-actionscript--extension-dir) (lsp-actionscript--extension-dir))
+ "com.as3mxml.vscode.Main"))
+
+(defun lsp-actionscript--extension-path-zip ()
+ "Change extension path from .vsix to .zip."
+ (concat (f-no-ext (lsp-actionscript--extension-path)) ".zip"))
+
+(lsp-dependency
+ 'as3mxml
+ '(:system "as3mxml")
+ `(:download :url lsp-actionscript-server-download-url
+ :store-path ,(lsp-actionscript--extension-path-zip)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ #'lsp-actionscript--server-command
+ (lambda () (f-exists? (lsp-actionscript--extension-path-zip))))
+ :major-modes '(actionscript-mode)
+ :priority -1
+ :server-id 'as3mxml-ls
+ :download-server-fn (lambda (_client _callback error-callback _update?)
+ (lsp-package-ensure
+ 'as3mxml
+ (lambda ()
+ ;; TODO: Error handling when unzip failed
+ (lsp-unzip (lsp-actionscript--extension-path-zip)
+ (lsp-actionscript--extension-root)))
+ error-callback))))
+
+(lsp-consistency-check lsp-actionscript)
+
+(provide 'lsp-actionscript)
+;;; lsp-actionscript.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ada.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ada.el
new file mode 100644
index 0000000..9b105b3
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ada.el
@@ -0,0 +1,74 @@
+;;; lsp-ada.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, ada
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Ada Programming Language
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-ada nil
+ "Settings for Ada Language Server."
+ :group 'tools
+ :tag "Language Server"
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-ada-project-file "default.gpr"
+ "Set the project file full path to configure the language server with.
+ The ~ prefix (for the user home directory) is supported.
+ See https://github.com/AdaCore/ada_language_server for a per-project
+ configuration example."
+ :type 'string
+ :group 'lsp-ada
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-ada-option-charset "UTF-8"
+ "The charset to use by the Ada Language server. Defaults to 'UTF-8'."
+ :type 'string
+ :group 'lsp-ada
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-ada-enable-diagnostics t
+ "A boolean to disable diagnostics. Defaults to true."
+ :type 'boolean
+ :group 'lsp-ada
+ :package-version '(lsp-mode . "6.2"))
+
+(lsp-register-custom-settings
+ '(("ada.projectFile" lsp-ada-project-file)
+ ("ada.enableDiagnostics" lsp-ada-enable-diagnostics)
+ ("ada.defaultCharset" lsp-ada-option-charset)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection '("ada_language_server"))
+ :major-modes '(ada-mode)
+ :priority -1
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "ada"))))
+ :server-id 'ada-ls))
+
+(lsp-consistency-check lsp-ada)
+
+(provide 'lsp-ada)
+;;; lsp-ada.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-angular.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-angular.el
new file mode 100644
index 0000000..65a021a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-angular.el
@@ -0,0 +1,82 @@
+;;; lsp-angular.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp,
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Angular Web application framework.
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'f)
+
+
+;;; Angular
+(defgroup lsp-angular nil
+ "Angular LSP client, provided by the Angular Language Service Server."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/angular/vscode-ng-language-service"))
+
+(defcustom lsp-clients-angular-language-server-command
+ nil
+ "The command that starts the angular language server."
+ :group 'lsp-angular
+ :type '(choice
+ (string :tag "Single string value")
+ (repeat :tag "List of string values"
+ string)))
+
+(defun lsp-client--angular-start-loading (_workspace params)
+ (lsp--info "Started loading project %s" params))
+
+(defun lsp-client--angular-finished-loading (_workspace params)
+ (lsp--info "Finished loading project %s" params))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda () (if lsp-clients-angular-language-server-command
+ lsp-clients-angular-language-server-command
+ (let ((node-modules-path
+ (concat (string-trim (shell-command-to-string "npm config get --global prefix"))
+ "/lib/node_modules")))
+ (list
+ "node"
+ (concat node-modules-path "/@angular/language-server")
+ "--ngProbeLocations"
+ node-modules-path
+ "--tsProbeLocations"
+ node-modules-path
+ "--stdio")))))
+ :activation-fn (lambda (&rest _args)
+ (and (string-match-p "\\(\\.html\\|\\.ts\\)\\'" (buffer-file-name))
+ (lsp-workspace-root)
+ (file-exists-p (f-join (lsp-workspace-root) "angular.json"))))
+ :priority -1
+ :notification-handlers (ht ("angular/projectLoadingStart" #'lsp-client--angular-start-loading)
+ ("angular/projectLoadingFinish" #'lsp-client--angular-finished-loading))
+ :add-on? t
+ :server-id 'angular-ls))
+
+
+(lsp-consistency-check lsp-angular)
+
+(provide 'lsp-angular)
+;;; lsp-angular.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-bash.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-bash.el
new file mode 100644
index 0000000..ee8a28e
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-bash.el
@@ -0,0 +1,90 @@
+;;; lsp-bash.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, bash, shell-script
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Bash Programming Language
+
+;;; Code:
+
+(require 'lsp-mode)
+
+;;; Bash
+(defgroup lsp-bash nil
+ "Settings for the Bash Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/bash-lsp/bash-language-server")
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-bash-explainshell-endpoint nil
+ "The endpoint to use explainshell.com to answer 'onHover' queries.
+See instructions at https://marketplace.visualstudio.com/items?itemName=mads-hartmann.bash-ide-vscode"
+ :type 'string
+ :risky t
+ :group 'lsp-bash
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-bash-highlight-parsing-errors nil
+ "Consider parsing errors in scripts as 'problems'."
+ :type 'boolean
+ :group 'lsp-bash
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-bash-glob-pattern nil
+ "Glob pattern used to find shell script files to parse."
+ :type 'string
+ :group 'lsp-bash
+ :package-version '(lsp-mode . "6.3"))
+
+(defun lsp-bash--bash-ls-server-command ()
+ "Startup command for Bash language server."
+ (list (lsp-package-path 'bash-language-server) "start"))
+
+(lsp-dependency 'bash-language-server
+ '(:system "bash-language-server")
+ '(:npm :package "bash-language-server"
+ :path "bash-language-server"))
+
+(defvar sh-shell)
+
+(defun lsp-bash-check-sh-shell (&rest _)
+ "Check whether `sh-shell' is sh or bash.
+
+This prevents the Bash server from being turned on in zsh files."
+ (and (eq major-mode 'sh-mode)
+ (memq sh-shell '(sh bash))))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-bash--bash-ls-server-command)
+ :priority -1
+ :activation-fn #'lsp-bash-check-sh-shell
+ :environment-fn (lambda ()
+ '(("EXPLAINSHELL_ENDPOINT" . lsp-bash-explainshell-endpoint)
+ ("HIGHLIGHT_PARSING_ERRORS" . lsp-bash-highlight-parsing-errors)
+ ("GLOB_PATTERN" . lsp-bash-glob-pattern)))
+ :server-id 'bash-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'bash-language-server callback error-callback))))
+
+(lsp-consistency-check lsp-bash)
+
+(provide 'lsp-bash)
+;;; lsp-bash.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-beancount.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-beancount.el
new file mode 100644
index 0000000..f1f8c74
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-beancount.el
@@ -0,0 +1,71 @@
+;;; lsp-beancount.el --- Beancount Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, beancount
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for Beancount
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-beancount nil
+ "Settings for the Beancount Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/polarmutex/beancount-language-server")
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-beancount-langserver-executable "beancount-langserver"
+ "Command to start Beancount language server."
+ :type 'string
+ :group 'lsp-beancount
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-beancount-python-interpreter nil
+ "Path to Python executable."
+ :type 'string
+ :group 'lsp-beancount
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-beancount-journal-file nil
+ "Pathg to Beancount journal file."
+ :type 'string
+ :group 'lsp-beancount
+ :package-version '(lsp-mode . "7.1.0"))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection
+ (lsp-stdio-connection
+ (lambda ()
+ (when (null lsp-beancount-python-interpreter)
+ (setq lsp-beancount-python-interpreter (or (executable-find "python3")
+ (executable-find "python"))))
+ `(,lsp-beancount-langserver-executable "--stdio")))
+ :major-modes '(beancount-mode)
+ :initialization-options
+ `((journalFile . ,lsp-beancount-journal-file)
+ (pythonPath . ,lsp-beancount-python-interpreter))
+ :server-id 'beancount-ls))
+
+(lsp-consistency-check lsp-beancount)
+
+(provide 'lsp-beancount)
+;;; lsp-beancount.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clangd.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clangd.el
new file mode 100644
index 0000000..fc37a17
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clangd.el
@@ -0,0 +1,304 @@
+;;; lsp-clangd.el --- LSP clients for the C Languages Family -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Daniel Martín & emacs-lsp maintainers
+;; URL: https://github.com/emacs-lsp/lsp-mode
+;; Keywords: languages, c, cpp, clang
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP clients for the C Languages Family.
+
+;; ** Clang-tidy Flycheck integration (Clangd) **
+;;
+;; If you invoke `flycheck-display-error-explanation' on a
+;; `clang-tidy' error (if Clangd is configured to show `clang-tidy'
+;; diagnostics), Emacs will open a detailed explanation about the
+;; message by querying the LLVM website. As an embedded web browser is
+;; used to show the documentation, this feature requires that Emacs is
+;; compiled with libxml2 support.
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'cl-lib)
+(require 'rx)
+(require 'seq)
+(require 'dom)
+(eval-when-compile (require 'subr-x))
+
+(require 'dash)
+(require 's)
+
+(defvar flycheck-explain-error-buffer)
+(declare-function flycheck-error-id "ext:flycheck" (err) t)
+(declare-function flycheck-error-group "ext:flycheck" (err) t)
+(declare-function flycheck-error-message "ext:flycheck" (err) t)
+
+(defcustom lsp-clangd-version "12.0.0"
+ "Clangd version to download.
+It has to be set before `lsp-clangd.el' is loaded and it has to
+be available here: https://github.com/clangd/clangd/releases/"
+ :type 'string
+ :group 'lsp-clangd
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-clangd-download-url
+ (format (pcase system-type
+ ('darwin "https://github.com/clangd/clangd/releases/download/%s/clangd-mac-%s.zip")
+ ('windows-nt "https://github.com/clangd/clangd/releases/download/%s/clangd-windows-%s.zip")
+ (_ "https://github.com/clangd/clangd/releases/download/%s/clangd-linux-%s.zip"))
+ lsp-clangd-version
+ lsp-clangd-version)
+ "Automatic download url for clangd"
+ :type 'string
+ :group 'lsp-clangd
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-clangd-binary-path
+ (f-join lsp-server-install-dir (format "clangd/clangd_%s/bin"
+ lsp-clangd-version)
+ (pcase system-type
+ ('windows-nt "clangd.exe")
+ (_ "clangd")))
+ "The path to `clangd' binary."
+ :type 'file
+ :group 'lsp-clangd
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-dependency
+ 'clangd
+ `(:download :url lsp-clangd-download-url
+ :decompress :zip
+ :store-path ,(f-join lsp-server-install-dir "clangd" "clangd.zip")
+ :binary-path lsp-clangd-binary-path
+ :set-executable? t))
+
+(defun lsp-cpp-flycheck-clang-tidy--skip-http-headers ()
+ "Position point just after HTTP headers."
+ (re-search-forward "^$"))
+
+(defun lsp-cpp-flycheck-clang-tidy--narrow-to-http-body ()
+ "Narrow the current buffer to contain the body of an HTTP response."
+ (lsp-cpp-flycheck-clang-tidy--skip-http-headers)
+ (narrow-to-region (point) (point-max)))
+
+(defun lsp-cpp-flycheck-clang-tidy--decode-region-as-utf8 (start end)
+ "Decode a region from START to END in UTF-8."
+ (condition-case nil
+ (decode-coding-region start end 'utf-8)
+ (coding-system-error nil)))
+
+(defun lsp-cpp-flycheck-clang-tidy--remove-crlf ()
+ "Remove carriage return and line feeds from the current buffer."
+ (save-excursion
+ (while (re-search-forward "\r$" nil t)
+ (replace-match "" t t))))
+
+(defun lsp-cpp-flycheck-clang-tidy--extract-relevant-doc-section ()
+ "Extract the parts of the LLVM clang-tidy documentation that are relevant.
+
+This function assumes that the current buffer contains the result
+of browsing 'clang.llvm.org', as returned by `url-retrieve'.
+More concretely, this function returns the main <div> element
+with class 'section', and also removes 'headerlinks'."
+ (goto-char (point-min))
+ (lsp-cpp-flycheck-clang-tidy--narrow-to-http-body)
+ (lsp-cpp-flycheck-clang-tidy--decode-region-as-utf8 (point-min) (point-max))
+ (lsp-cpp-flycheck-clang-tidy--remove-crlf)
+ (let* ((dom (libxml-parse-html-region (point-min) (point-max)))
+ (section (dom-by-class dom "section")))
+ (dolist (headerlink (dom-by-class section "headerlink"))
+ (dom-remove-node section headerlink))
+ section))
+
+(defun lsp-cpp-flycheck-clang-tidy--explain-error (explanation &rest args)
+ "Explain an error in the Flycheck error explanation buffer using EXPLANATION.
+
+EXPLANATION is a function with optional ARGS that, when
+evaluated, inserts the content in the appropriate Flycheck
+buffer."
+ (with-current-buffer flycheck-explain-error-buffer
+ (let ((inhibit-read-only t)
+ (inhibit-modification-hooks t))
+ (erase-buffer)
+ (apply explanation args)
+ (goto-char (point-min)))))
+
+(defun lsp-cpp-flycheck-clang-tidy--show-loading-status ()
+ "Show a loading string while clang-tidy documentation is fetched from llvm.org.
+Recent versions of `flycheck' call `display-message-or-buffer' to
+display error explanations. `display-message-or-buffer' displays
+the documentation string either in the echo area or in a separate
+window, depending on the string's height. This function forces to
+always display it in a separate window by appending the required
+number of newlines."
+ (let* ((num-lines-threshold
+ (round (if resize-mini-windows
+ (cond ((floatp max-mini-window-height)
+ (* (frame-height)
+ max-mini-window-height))
+ ((integerp max-mini-window-height)
+ max-mini-window-height)
+ (t
+ 1))
+ 1)))
+ (extra-new-lines (make-string (1+ num-lines-threshold) ?\n)))
+ (concat "Loading documentation..." extra-new-lines)))
+
+(defun lsp-cpp-flycheck-clang-tidy--show-documentation (error-id)
+ "Show clang-tidy documentation about ERROR-ID.
+
+Information comes from the clang.llvm.org website."
+ (url-retrieve (format
+ "https://clang.llvm.org/extra/clang-tidy/checks/%s.html" error-id)
+ (lambda (status)
+ (if-let ((error-status (plist-get status :error)))
+ (lsp-cpp-flycheck-clang-tidy--explain-error
+ #'insert
+ (format
+ "Error accessing clang-tidy documentation: %s"
+ (error-message-string error-status)))
+ (let ((doc-contents
+ (lsp-cpp-flycheck-clang-tidy--extract-relevant-doc-section)))
+ (lsp-cpp-flycheck-clang-tidy--explain-error
+ #'shr-insert-document doc-contents)))))
+ (lsp-cpp-flycheck-clang-tidy--show-loading-status))
+
+;;;###autoload
+(defun lsp-cpp-flycheck-clang-tidy-error-explainer (error)
+ "Explain a clang-tidy ERROR by scraping documentation from llvm.org."
+ (unless (fboundp 'libxml-parse-html-region)
+ (error "This function requires Emacs to be compiled with libxml2"))
+ (if-let ((clang-tidy-error-id (flycheck-error-id error)))
+ (condition-case err
+ (lsp-cpp-flycheck-clang-tidy--show-documentation clang-tidy-error-id)
+ (error
+ (format
+ "Error accessing clang-tidy documentation: %s"
+ (error-message-string err))))
+ (error "The clang-tidy error message does not contain an [error-id]")))
+
+
+;;; lsp-clangd
+(defgroup lsp-clangd nil
+ "LSP support for C-family languages (C, C++, Objective-C, Objective-C++), using clangd."
+ :group 'lsp-mode
+ :link '(url-link "https://clang.llvm.org/extra/clangd"))
+
+(defcustom lsp-clients-clangd-executable nil
+ "The clangd executable to use.
+When `'non-nil' use the name of the clangd executable file
+available in your path to use. Otherwise the system will try to
+find a suitable one. Set this variable before loading lsp."
+ :group 'lsp-clangd
+ :risky t
+ :type '(choice (file :tag "Path")
+ (const :tag "Auto" nil)))
+
+(defvar lsp-clients--clangd-default-executable nil
+ "Clang default executable full path when found.
+This must be set only once after loading the clang client.")
+
+(defcustom lsp-clients-clangd-args '("--header-insertion-decorators=0")
+ "Extra arguments for the clangd executable."
+ :group 'lsp-clangd
+ :risky t
+ :type '(repeat string))
+
+(defun lsp-clients--clangd-command ()
+ "Generate the language server startup command."
+ (unless lsp-clients--clangd-default-executable
+ (setq lsp-clients--clangd-default-executable
+ (or (lsp-package-path 'clangd)
+ (-first #'executable-find
+ (-map (lambda (version)
+ (concat "clangd" version))
+ '("" "-12" "-11" "-10" "-9" "-8" "-7" "-6")))
+ (lsp-clients-executable-find "xcodebuild" "-find-executable" "clangd")
+ (lsp-clients-executable-find "xcrun" "--find" "clangd"))))
+
+ `(,(or lsp-clients-clangd-executable lsp-clients--clangd-default-executable "clangd")
+ ,@lsp-clients-clangd-args))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ 'lsp-clients--clangd-command)
+ :activation-fn (lsp-activate-on "c" "cpp" "objective-c")
+ :priority -1
+ :server-id 'clangd
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'clangd callback error-callback))))
+
+(defun lsp-clangd-join-region (beg end)
+ "Apply join-line from BEG to END.
+This function is useful when an indented function prototype needs
+to be shown in a single line."
+ (save-excursion
+ (let ((end (copy-marker end)))
+ (goto-char beg)
+ (while (< (point) end)
+ (join-line 1)))
+ (s-trim (buffer-string))))
+
+(cl-defmethod lsp-clients-extract-signature-on-hover (contents (_server-id (eql clangd)))
+ "Extract a representative line from clangd's CONTENTS, to show in the echo area.
+This function tries to extract the type signature from CONTENTS,
+or the first line if it cannot do so. A single line is always
+returned to avoid that the echo area grows uncomfortably."
+ (with-temp-buffer
+ (-let [value (lsp:markup-content-value contents)]
+ (insert value)
+ (goto-char (point-min))
+ (if (re-search-forward (rx (seq "```cpp\n"
+ (opt (group "//"
+ (zero-or-more nonl)
+ "\n"))
+ (group
+ (one-or-more
+ (not (any "`")))
+ "\n")
+ "```")) nil t nil)
+ (progn (narrow-to-region (match-beginning 2) (match-end 2))
+ (lsp--render-element (lsp-make-marked-string
+ :language "cpp"
+ :value (lsp-clangd-join-region (point-min) (point-max)))))
+ (car (s-lines (lsp--render-element contents)))))))
+
+(cl-defmethod lsp-diagnostics-flycheck-error-explainer (e (_server-id (eql clangd)))
+ "Explain a `flycheck-error' E that was generated by the Clangd language server."
+ (cond ((string-equal "clang-tidy" (flycheck-error-group e))
+ (lsp-cpp-flycheck-clang-tidy-error-explainer e))
+ (t (flycheck-error-message e))))
+
+(defun lsp-clangd-find-other-file (&optional new-window)
+ "Switch between the corresponding C/C++ source and header file.
+If NEW-WINDOW (interactively the prefix argument) is non-nil,
+open in a new window.
+
+Only works with clangd."
+ (interactive "P")
+ (let ((other (lsp-send-request (lsp-make-request
+ "textDocument/switchSourceHeader"
+ (lsp--text-document-identifier)))))
+ (unless (s-present? other)
+ (user-error "Could not find other file"))
+ (funcall (if new-window #'find-file-other-window #'find-file)
+ (lsp--uri-to-path other))))
+
+(lsp-consistency-check lsp-clangd)
+
+(provide 'lsp-clangd)
+;;; lsp-clangd.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clojure.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clojure.el
new file mode 100644
index 0000000..9855983
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-clojure.el
@@ -0,0 +1,308 @@
+;;; lsp-clojure.el --- Clojure Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Benedek Fazekas
+
+;; Author: Benedek Fazekas <benedek.fazekas@gmail.com>
+;; Keywords: languages,tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-clojure client
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'lsp-protocol)
+(require 'cl-lib)
+
+(defgroup lsp-clojure nil
+ "LSP support for Clojure."
+ :link '(url-link "https://github.com/snoe/clojure-lsp")
+ :group 'lsp-mode
+ :tag "Lsp Clojure")
+
+(define-obsolete-variable-alias 'lsp-clojure-server-command
+ 'lsp-clojure-custom-server-command "lsp-mode 7.1")
+
+(defcustom lsp-clojure-custom-server-command nil
+ "The clojure-lisp server command."
+ :group 'lsp-clojure
+ :risky t
+ :type '(repeat string))
+
+(defcustom lsp-clojure-server-download-url
+ (format "https://github.com/clojure-lsp/clojure-lsp/releases/latest/download/clojure-lsp-native-%s-amd64.zip"
+ (pcase system-type
+ ('gnu/linux "linux")
+ ('darwin "macos")
+ ('windows-nt "windows")))
+ "Automatic download url for lsp-clojure."
+ :type 'string
+ :group 'lsp-clojure
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-clojure-server-store-path
+ (f-join lsp-server-install-dir
+ "clojure"
+ (if (eq system-type 'windows-nt)
+ "clojure-lsp.exe"
+ "clojure-lsp"))
+ "The path to the file in which `clojure-lsp' will be stored."
+ :type 'file
+ :group 'lsp-clojure
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-clojure-workspace-dir (expand-file-name (locate-user-emacs-file "workspace/"))
+ "LSP clojure workspace directory."
+ :group 'lsp-clojure
+ :risky t
+ :type 'directory)
+
+(defcustom lsp-clojure-workspace-cache-dir (expand-file-name ".cache/" lsp-clojure-workspace-dir)
+ "LSP clojure workspace cache directory."
+ :group 'lsp-clojure
+ :risky t
+ :type 'directory)
+
+;; Internal
+
+(lsp-interface
+ (Clojure:CursorInfoParams (:textDocument :position) nil))
+
+(lsp-dependency
+ 'clojure-lsp
+ `(:download :url lsp-clojure-server-download-url
+ :decompress :zip
+ :store-path lsp-clojure-server-store-path
+ :set-executable? t)
+ '(:system "clojure-lsp"))
+
+;; Refactorings
+
+(defun lsp-clojure--execute-command (command &optional args)
+ "Send an executeCommand request for COMMAND with ARGS."
+ (lsp--cur-workspace-check)
+ (lsp-send-execute-command command (apply #'vector args)))
+
+(defun lsp-clojure--refactoring-call (refactor-name &rest additional-args)
+ "Send an executeCommand request for REFACTOR-NAME with ADDITIONAL-ARGS.
+If there are more arguments expected after the line and column numbers."
+ (lsp--cur-workspace-check)
+ (lsp-clojure--execute-command refactor-name (cl-list* (lsp--buffer-uri)
+ (- (line-number-at-pos) 1) ;; clojure-lsp expects line numbers to start at 0
+ (current-column)
+ additional-args)))
+
+(defun lsp-clojure-add-import-to-namespace (import-name)
+ "Add to IMPORT-NAME to :import form."
+ (interactive "MImport name: ")
+ (lsp-clojure--refactoring-call "add-import-to-namespace" import-name))
+
+(defun lsp-clojure-add-missing-libspec ()
+ "Apply add-missing-libspec refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "add-missing-libspec"))
+
+(defun lsp-clojure-clean-ns ()
+ "Apply clean-ns refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "clean-ns"))
+
+(defun lsp-clojure-cycle-coll ()
+ "Apply cycle-coll refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "cycle-coll"))
+
+(defun lsp-clojure-cycle-privacy ()
+ "Apply cycle-privacy refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "cycle-privacy"))
+
+(defun lsp-clojure-expand-let ()
+ "Apply expand-let refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "expand-let"))
+
+(defun lsp-clojure-extract-function (function-name)
+ "Move form at point into a new function named FUNCTION-NAME."
+ (interactive "MFunction name: ") ;; Name of the function
+ (lsp-clojure--refactoring-call "extract-function" function-name))
+
+(defun lsp-clojure-inline-symbol ()
+ "Apply inline-symbol refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "inline-symbol"))
+
+(defun lsp-clojure-introduce-let (binding-name)
+ "Move form at point into a new let binding as BINDING-NAME."
+ (interactive "MBinding name: ") ;; Name of the let binding
+ (lsp-clojure--refactoring-call "introduce-let" binding-name))
+
+(defun lsp-clojure-move-to-let (binding-name)
+ "Move form at point into nearest existing let binding as BINDING-NAME."
+ (interactive "MBinding name: ") ;; Name of the let binding
+ (lsp-clojure--refactoring-call "move-to-let" binding-name))
+
+(defun lsp-clojure-thread-first ()
+ "Apply thread-first refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "thread-first"))
+
+(defun lsp-clojure-thread-first-all ()
+ "Apply thread-first-all refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "thread-first-all"))
+
+(defun lsp-clojure-thread-last ()
+ "Apply thread-last refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "thread-last"))
+
+(defun lsp-clojure-thread-last-all ()
+ "Apply thread-last-all refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "thread-last-all"))
+
+(defun lsp-clojure-unwind-all ()
+ "Apply unwind-all refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "unwind-all"))
+
+(defun lsp-clojure-unwind-thread ()
+ "Apply unwind-thread refactoring at point."
+ (interactive)
+ (lsp-clojure--refactoring-call "unwind-thread"))
+
+(defun lsp-clojure-server-info ()
+ "Request server info."
+ (interactive)
+ (lsp--cur-workspace-check)
+ (lsp-notify "clojure/serverInfo/log" nil))
+
+(defun lsp-clojure-server-info-raw ()
+ "Request server info raw data."
+ (interactive)
+ (lsp--cur-workspace-check)
+ (message "%s" (lsp--json-serialize (lsp-request "clojure/serverInfo/raw" nil))))
+
+(defun lsp-clojure-cursor-info ()
+ "Request cursor info at point."
+ (interactive)
+ (lsp--cur-workspace-check)
+ (lsp-notify "clojure/cursorInfo/log"
+ (lsp-make-clojure-cursor-info-params
+ :textDocument (lsp-make-text-document-identifier :uri (lsp--buffer-uri))
+ :position (lsp-make-position :line (- (line-number-at-pos) 1)
+ :character (current-column)))))
+
+(defun lsp-clojure--ask-macro-to-resolve ()
+ "Ask to user the macro to resolve."
+ (lsp--completing-read
+ "Select how LSP should resolve this macro:"
+ '("clojure.core/def"
+ "clojure.core/defn"
+ "clojure.core/let"
+ "clojure.core/for"
+ "clojure.core/->"
+ "clojure.core/->>"
+ "clj-kondo.lint-as/def-catch-all")
+ #'identity
+ nil
+ t))
+
+(defun lsp-clojure--ask-clj-kondo-config-dir ()
+ "Ask to user the clj-kondo config dir path."
+ (lsp--completing-read
+ "Select where LSP should save this setting:"
+ (list (f-join (expand-file-name "~/") ".config/clj-kondo/config.edn")
+ (f-join (or (lsp-workspace-root) "project") ".clj-kondo/config.edn"))
+ #'identity
+ nil
+ t))
+
+(defun lsp-clojure-resolve-macro-as ()
+ "Ask to user how the unresolved macro should be resolved."
+ (interactive)
+ (lsp--cur-workspace-check)
+ (lsp-clojure--execute-command "resolve-macro-as"
+ (list (lsp--buffer-uri)
+ (- (line-number-at-pos) 1) ;; clojure-lsp expects line numbers to start at 0
+ (current-column)
+ (lsp-clojure--ask-macro-to-resolve)
+ (lsp-clojure--ask-clj-kondo-config-dir))))
+
+(lsp-defun lsp-clojure--resolve-macro-as ((&Command :command :arguments?))
+ "Intercept resolve-macro-as command and send all necessary data."
+ (let ((chosen-macro (lsp-clojure--ask-macro-to-resolve))
+ (clj-kondo-config-path (lsp-clojure--ask-clj-kondo-config-dir)))
+ (lsp-clojure--execute-command command (append arguments? (list chosen-macro clj-kondo-config-path)))))
+
+(defun lsp-clojure--ensure-dir (path)
+ "Ensure that directory PATH exists."
+ (unless (file-directory-p path)
+ (make-directory path t)))
+
+(defun lsp-clojure--get-metadata-location (file-location)
+ "Given a FILE-LOCATION return the file containing the metadata for the file."
+ (format "%s.%s.metadata"
+ (file-name-directory file-location)
+ (file-name-base file-location)))
+
+(defun lsp-clojure--file-in-jar (uri)
+ "Check URI for a valid jar and include it in workspace."
+ (string-match "^\\(jar\\|zip\\):\\(file:.+\\)!/\\(.+\\)" uri)
+ (let* ((ns-path (match-string 3 uri))
+ (ns (s-replace "/" "." ns-path))
+ (file-location (concat lsp-clojure-workspace-cache-dir ns)))
+ (unless (file-readable-p file-location)
+ (lsp-clojure--ensure-dir (file-name-directory file-location))
+ (with-lsp-workspace (lsp-find-workspace 'clojure-lsp nil)
+ (let ((content (lsp-send-request (lsp-make-request "clojure/dependencyContents" (list :uri uri)))))
+ (with-temp-file file-location
+ (insert content))
+ (with-temp-file (lsp-clojure--get-metadata-location file-location)
+ (insert uri)))))
+ file-location))
+
+(defun lsp-clojure--server-executable-path ()
+ "Return the clojure-lsp server command."
+ (or (executable-find "clojure-lsp")
+ (lsp-package-path 'clojure-lsp)))
+
+(lsp-register-client
+ (make-lsp-client
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'clojure-lsp callback error-callback))
+ :semantic-tokens-faces-overrides '(:types (("macro" . font-lock-keyword-face)
+ ("keyword" . clojure-keyword-face)))
+ :new-connection (lsp-stdio-connection
+ (lambda ()
+ (or lsp-clojure-custom-server-command
+ `(,(lsp-clojure--server-executable-path))))
+ (lambda ()
+ (or lsp-clojure-custom-server-command
+ (lsp-clojure--server-executable-path))))
+ :major-modes '(clojure-mode clojurec-mode clojurescript-mode)
+ :library-folders-fn (lambda (_workspace) (list lsp-clojure-workspace-cache-dir))
+ :uri-handlers (lsp-ht ("jar" #'lsp-clojure--file-in-jar))
+ :action-handlers (lsp-ht ("resolve-macro-as" #'lsp-clojure--resolve-macro-as))
+ :initialization-options '(:dependency-scheme "jar")
+ :server-id 'clojure-lsp))
+
+(lsp-consistency-check lsp-clojure)
+
+(provide 'lsp-clojure)
+;;; lsp-clojure.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-cmake.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-cmake.el
new file mode 100644
index 0000000..beffa5d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-cmake.el
@@ -0,0 +1,43 @@
+;;; lsp-cmake.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, cmake
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the CMake build tool.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-cmake nil
+ "LSP support for CMake, using cmake-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/regen100/cmake-language-server"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection "cmake-language-server")
+ :major-modes '(cmake-mode)
+ :priority -1
+ :server-id 'cmakels))
+
+(lsp-consistency-check lsp-cmake)
+
+(provide 'lsp-cmake)
+;;; lsp-cmake.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-completion.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-completion.el
new file mode 100644
index 0000000..d8d131e
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-completion.el
@@ -0,0 +1,779 @@
+;;; lsp-completion.el --- LSP completion -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP completion
+;;
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-completion nil
+ "LSP support for completion"
+ :prefix "lsp-completion-"
+ :group 'lsp-mode
+ :tag "LSP Completion")
+
+;;;###autoload
+(define-obsolete-variable-alias 'lsp-prefer-capf
+ 'lsp-completion-provider "lsp-mode 7.0.1")
+
+(defcustom lsp-completion-provider :capf
+ "The completion backend provider."
+ :type '(choice
+ (const :tag "Use company-capf" :capf)
+ (const :tag "None" :none))
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.0.1"))
+
+;;;###autoload
+(define-obsolete-variable-alias 'lsp-enable-completion-at-point
+ 'lsp-completion-enable "lsp-mode 7.0.1")
+
+(defcustom lsp-completion-enable t
+ "Enable `completion-at-point' integration."
+ :type 'boolean
+ :group 'lsp-completion)
+
+(defcustom lsp-completion-enable-additional-text-edit t
+ "Whether or not to apply additional text edit when performing completion.
+
+If set to non-nil, `lsp-mode' will apply additional text edits
+from the server. Otherwise, the additional text edits are
+ignored."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-completion-show-kind t
+ "Whether or not to show kind of completion candidates."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-completion-show-detail t
+ "Whether or not to show detail of completion candidates."
+ :type 'boolean
+ :group 'lsp-completion)
+
+(defcustom lsp-completion-no-cache nil
+ "Whether or not caching the returned completions from server."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-completion-filter-on-incomplete t
+ "Whether or not filter incomplete results."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-completion-sort-initial-results t
+ "Whether or not filter initial results from server."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-completion-use-last-result t
+ "Temporarily use last server result when interrupted by keyboard.
+This will help minimize popup flickering issue in `company-mode'."
+ :type 'boolean
+ :group 'lsp-completion
+ :package-version '(lsp-mode . "7.1"))
+
+(defconst lsp-completion--item-kind
+ [nil
+ "Text"
+ "Method"
+ "Function"
+ "Constructor"
+ "Field"
+ "Variable"
+ "Class"
+ "Interface"
+ "Module"
+ "Property"
+ "Unit"
+ "Value"
+ "Enum"
+ "Keyword"
+ "Snippet"
+ "Color"
+ "File"
+ "Reference"
+ "Folder"
+ "EnumMember"
+ "Constant"
+ "Struct"
+ "Event"
+ "Operator"
+ "TypeParameter"])
+
+(defvar yas-indent-line)
+(defvar company-backends)
+(defvar company-abort-on-unique-match)
+
+(defvar lsp-completion--no-reordering nil
+ "Dont do client-side reordering completion items when set.")
+
+(declare-function company-mode "ext:company")
+(declare-function company-doc-buffer "ext:company")
+(declare-function yas-expand-snippet "ext:yasnippet")
+
+(defun lsp-falsy? (val)
+ "Non-nil if VAL is falsy."
+ ;; https://developer.mozilla.org/en-US/docs/Glossary/Falsy
+ (or (not val) (equal val "") (equal val 0)))
+
+(cl-defun lsp-completion--make-item (item &key markers prefix)
+ "Make completion item from lsp ITEM and with MARKERS and PREFIX."
+ (-let (((&CompletionItem :label
+ :sort-text?
+ :_emacsStartPoint start-point)
+ item))
+ (propertize label
+ 'lsp-completion-item item
+ 'lsp-sort-text sort-text?
+ 'lsp-completion-start-point start-point
+ 'lsp-completion-markers markers
+ 'lsp-completion-prefix prefix)))
+
+(defun lsp-completion--annotate (item)
+ "Annotate ITEM detail."
+ (-let (((&CompletionItem :detail? :kind?) (plist-get (text-properties-at 0 item)
+ 'lsp-completion-item)))
+ (concat (when (and lsp-completion-show-detail detail?)
+ (concat " " (s-replace "\r" "" detail?)))
+ (when lsp-completion-show-kind
+ (when-let ((kind-name (and kind? (aref lsp-completion--item-kind kind?))))
+ (format " (%s)" kind-name))))))
+
+(defun lsp-completion--looking-back-trigger-characterp (trigger-characters)
+ "Return trigger character if text before point match any of the TRIGGER-CHARACTERS."
+ (unless (= (point) (point-at-bol))
+ (seq-some
+ (lambda (trigger-char)
+ (and (equal (buffer-substring-no-properties (- (point) (length trigger-char)) (point))
+ trigger-char)
+ trigger-char))
+ trigger-characters)))
+
+(defvar lsp-completion--cache nil
+ "Cached candidates for completion at point function.
+In the form of plist (prefix-pos items :lsp-items :prefix ...).
+When the completion is incomplete, `items' contains value of :incomplete.")
+
+(defvar lsp-completion--last-result nil
+ "Last completion result.")
+
+(defun lsp-completion--clear-cache (&optional keep-last-result)
+ "Clear completion caches.
+KEEP-LAST-RESULT if specified."
+ (-some-> lsp-completion--cache
+ (cddr)
+ (plist-get :markers)
+ (cl-second)
+ (set-marker nil))
+ (setq lsp-completion--cache nil)
+ (unless keep-last-result (setq lsp-completion--last-result nil)))
+
+(defcustom lsp-completion-default-behaviour :replace
+ "Default behaviour of `InsertReplaceEdit'."
+ :type '(choice
+ (const :insert :tag "Default completion inserts")
+ (const :replace :tag "Default completion replaces"))
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-defun lsp-completion--guess-prefix ((item &as &CompletionItem :text-edit?))
+ "Guess ITEM's prefix start point according to following heuristics:
+- If `textEdit' exists, use insertion range start as prefix start point.
+- Else, find the point before current point is longest prefix match of
+`insertText' or `label'. And:
+ - The character before prefix is not word constitute
+Return `nil' when fails to guess prefix."
+ (cond
+ ((lsp-insert-replace-edit? text-edit?)
+ (lsp--position-to-point (lsp:range-start (lsp:insert-replace-edit-insert text-edit?))))
+ (text-edit?
+ (lsp--position-to-point (lsp:range-start (lsp:text-edit-range text-edit?))))
+ (t
+ (-let* (((&CompletionItem :label :insert-text?) item)
+ (text (or (unless (lsp-falsy? insert-text?) insert-text?) label))
+ (point (point))
+ (start (max 1 (- point (length text))))
+ (char-before (char-before start))
+ start-point)
+ (while (and (< start point) (not start-point))
+ (unless (or (and char-before (equal (char-syntax char-before) ?w))
+ (not (string-prefix-p (buffer-substring-no-properties start point)
+ text)))
+ (setq start-point start))
+ (cl-incf start)
+ (setq char-before (char-before start)))
+ start-point))))
+
+(defun lsp-completion--to-internal (items)
+ "Convert ITEMS into internal form."
+ (--> items
+ (-map (-lambda ((item &as &CompletionItem
+ :label
+ :filter-text?
+ :_emacsStartPoint start-point
+ :score?))
+ `( :label ,(or (unless (lsp-falsy? filter-text?) filter-text?) label)
+ :item ,item
+ :start-point ,start-point
+ :score ,score?))
+ it)))
+
+(cl-defun lsp-completion--filter-candidates (items &key
+ lsp-items
+ markers
+ prefix
+ &allow-other-keys)
+ "List all possible completions in cached ITEMS with their prefixes.
+We can pass LSP-ITEMS, which will be used when there's no cache.
+The MARKERS and PREFIX value will be attached to each candidate."
+ (lsp--while-no-input
+ (->>
+ (if items
+ (-->
+ (let (queries fuz-queries)
+ (-keep (-lambda ((cand &as &plist :label :start-point :score))
+ (let* ((query (or (plist-get queries start-point)
+ (let ((s (buffer-substring-no-properties
+ start-point (point))))
+ (setq queries (plist-put queries start-point s))
+ s)))
+ (fuz-query (or (plist-get fuz-queries start-point)
+ (let ((s (lsp-completion--regex-fuz query)))
+ (setq fuz-queries
+ (plist-put fuz-queries start-point s))
+ s)))
+ (label-len (length label)))
+ (when (string-match fuz-query label)
+ (put-text-property 0 label-len 'match-data (match-data) label)
+ (plist-put cand
+ :sort-score
+ (* (or (lsp-completion--fuz-score query label) 1e-05)
+ (or score 0.001)))
+ cand)))
+ items))
+ (if lsp-completion--no-reordering
+ it
+ (sort it (lambda (o1 o2)
+ (> (plist-get o1 :sort-score)
+ (plist-get o2 :sort-score)))))
+ ;; TODO: pass additional function to sort the candidates
+ (-map (-rpartial #'plist-get :item) it))
+ lsp-items)
+ (-map (lambda (item) (lsp-completion--make-item item
+ :markers markers
+ :prefix prefix))))))
+
+(defconst lsp-completion--kind->symbol
+ '((1 . text)
+ (2 . method)
+ (3 . function)
+ (4 . constructor)
+ (5 . field)
+ (6 . variable)
+ (7 . class)
+ (8 . interface)
+ (9 . module)
+ (10 . property)
+ (11 . unit)
+ (12 . value)
+ (13 . enum)
+ (14 . keyword)
+ (15 . snippet)
+ (16 . color)
+ (17 . file)
+ (18 . reference)
+ (19 . folder)
+ (20 . enum-member)
+ (21 . constant)
+ (22 . struct)
+ (23 . event)
+ (24 . operator)
+ (25 . type-parameter)))
+
+(defun lsp-completion--candidate-kind (item)
+ "Return ITEM's kind."
+ (alist-get (lsp:completion-item-kind? (get-text-property 0 'lsp-completion-item item))
+ lsp-completion--kind->symbol))
+
+(defun lsp-completion--company-match (candidate)
+ "Return highlight of typed prefix inside CANDIDATE."
+ (let* ((prefix (downcase
+ (buffer-substring-no-properties
+ (plist-get (text-properties-at 0 candidate) 'lsp-completion-start-point)
+ (point))))
+ (prefix-len (length prefix))
+ (prefix-pos 0)
+ (label (downcase candidate))
+ (label-len (length label))
+ (label-pos 0)
+ matches start)
+ (while (and (not matches)
+ (< prefix-pos prefix-len))
+ (while (and (< prefix-pos prefix-len)
+ (< label-pos label-len))
+ (if (equal (aref prefix prefix-pos) (aref label label-pos))
+ (progn
+ (unless start (setq start label-pos))
+ (cl-incf prefix-pos))
+ (when start
+ (setq matches (nconc matches `((,start . ,label-pos))))
+ (setq start nil)))
+ (cl-incf label-pos))
+ (when start (setq matches (nconc matches `((,start . ,label-pos)))))
+ ;; Search again when the whole prefix is not matched
+ (when (< prefix-pos prefix-len)
+ (setq matches nil))
+ ;; Start search from next offset of prefix to find a match with label
+ (unless matches
+ (cl-incf prefix-pos)
+ (setq label-pos 0)))
+ matches))
+
+(defun lsp-completion--get-documentation (item)
+ "Get doc comment for completion ITEM."
+ (unless (get-text-property 0 'lsp-completion-resolved item)
+ (let ((resolved-item
+ (-some->> item
+ (get-text-property 0 'lsp-completion-item)
+ (lsp-completion--resolve)))
+ (len (length item)))
+ (put-text-property 0 len 'lsp-completion-item resolved-item item)
+ (put-text-property 0 len 'lsp-completion-resolved t item)))
+ (-some->> item
+ (get-text-property 0 'lsp-completion-item)
+ (lsp:completion-item-documentation?)
+ (lsp--render-element)))
+
+(defun lsp-completion--get-context (trigger-characters)
+ "Get completion context with provided TRIGGER-CHARACTERS."
+ (let* ((triggered-by-char non-essential)
+ (trigger-char (when triggered-by-char
+ (lsp-completion--looking-back-trigger-characterp
+ trigger-characters)))
+ (trigger-kind (cond
+ (trigger-char
+ lsp/completion-trigger-kind-trigger-character)
+ ((equal (cl-second lsp-completion--cache) :incomplete)
+ lsp/completion-trigger-kind-trigger-for-incomplete-completions)
+ (t lsp/completion-trigger-kind-invoked))))
+ (apply #'lsp-make-completion-context
+ (nconc
+ `(:trigger-kind ,trigger-kind)
+ (when trigger-char
+ `(:trigger-character? ,trigger-char))))))
+
+(defun lsp-completion--sort-completions (completions)
+ "Sort COMPLETIONS."
+ (sort
+ completions
+ (-lambda ((&CompletionItem :sort-text? sort-text-left :label label-left)
+ (&CompletionItem :sort-text? sort-text-right :label label-right))
+ (if (equal sort-text-left sort-text-right)
+ (string-lessp label-left label-right)
+ (string-lessp sort-text-left sort-text-right)))))
+
+;;;###autoload
+(defun lsp-completion-at-point ()
+ "Get lsp completions."
+ (when (or (--some (lsp--client-completion-in-comments? (lsp--workspace-client it))
+ (lsp-workspaces))
+ (not (nth 4 (syntax-ppss))))
+ (let* ((trigger-chars (->> (lsp--server-capabilities)
+ (lsp:server-capabilities-completion-provider?)
+ (lsp:completion-options-trigger-characters?)))
+ (bounds-start (or (-some--> (cl-first (bounds-of-thing-at-point 'symbol))
+ (save-excursion
+ (ignore-errors
+ (goto-char (+ it 1))
+ (while (lsp-completion--looking-back-trigger-characterp
+ trigger-chars)
+ (cl-incf it)
+ (forward-char))
+ it)))
+ (point)))
+ result done?
+ (candidates
+ (lambda ()
+ (lsp--catch 'input
+ (let ((lsp--throw-on-input lsp-completion-use-last-result)
+ (same-session? (and lsp-completion--cache
+ ;; Special case for empty prefix and empty result
+ (or (cl-second lsp-completion--cache)
+ (not (string-empty-p
+ (plist-get (cddr lsp-completion--cache) :prefix))))
+ (equal (cl-first lsp-completion--cache) bounds-start)
+ (s-prefix?
+ (plist-get (cddr lsp-completion--cache) :prefix)
+ (buffer-substring-no-properties bounds-start (point))))))
+ (cond
+ ((or done? result) result)
+ ((and (not lsp-completion-no-cache)
+ same-session?
+ (listp (cl-second lsp-completion--cache)))
+ (setf result (apply #'lsp-completion--filter-candidates
+ (cdr lsp-completion--cache))))
+ (t
+ (-let* ((resp (lsp-request-while-no-input
+ "textDocument/completion"
+ (plist-put (lsp--text-document-position-params)
+ :context (lsp-completion--get-context trigger-chars))))
+ (completed (and resp
+ (not (and (lsp-completion-list? resp)
+ (lsp:completion-list-is-incomplete resp)))))
+ (items (lsp--while-no-input
+ (--> (cond
+ ((lsp-completion-list? resp)
+ (lsp:completion-list-items resp))
+ (t resp))
+ (if (or completed
+ (seq-some #'lsp:completion-item-sort-text? it))
+ (lsp-completion--sort-completions it)
+ it)
+ (-map (lambda (item)
+ (lsp-put item
+ :_emacsStartPoint
+ (or (lsp-completion--guess-prefix item)
+ bounds-start)))
+ it))))
+ (markers (list bounds-start (copy-marker (point) t)))
+ (prefix (buffer-substring-no-properties bounds-start (point)))
+ (lsp-completion--no-reordering (not lsp-completion-sort-initial-results)))
+ (lsp-completion--clear-cache same-session?)
+ (setf done? completed
+ lsp-completion--cache (list bounds-start
+ (cond
+ ((and done? (not (seq-empty-p items)))
+ (lsp-completion--to-internal items))
+ ((not done?) :incomplete))
+ :lsp-items nil
+ :markers markers
+ :prefix prefix)
+ result (lsp-completion--filter-candidates
+ (cond (done?
+ (cl-second lsp-completion--cache))
+ (lsp-completion-filter-on-incomplete
+ (lsp-completion--to-internal items)))
+ :lsp-items items
+ :markers markers
+ :prefix prefix))))))
+ (:interrupted lsp-completion--last-result)
+ (`,res (setq lsp-completion--last-result res))))))
+ (list
+ bounds-start
+ (point)
+ (lambda (probe _pred action)
+ (cond
+ ;; metadata
+ ((equal action 'metadata)
+ `(metadata (category . lsp-capf)
+ (display-sort-function . identity)))
+ ;; boundaries
+ ((equal (car-safe action) 'boundaries) nil)
+ ;; try-completion
+ ((null action)
+ (when-let ((cands (funcall candidates)))
+ (if (cl-rest cands) probe (cl-first cands))))
+ ;; test-completion: not return exact match so that the selection will
+ ;; always be shown
+ ((equal action 'lambda) nil)
+ ;; retrieve candidates
+ ((equal action t) (funcall candidates))))
+ :annotation-function #'lsp-completion--annotate
+ :company-kind #'lsp-completion--candidate-kind
+ :company-require-match 'never
+ :company-prefix-length
+ (save-excursion
+ (goto-char bounds-start)
+ (and (lsp-completion--looking-back-trigger-characterp trigger-chars) t))
+ :company-match #'lsp-completion--company-match
+ :company-doc-buffer (-compose #'company-doc-buffer
+ #'lsp-completion--get-documentation)
+ :exit-function
+ (-rpartial #'lsp-completion--exit-fn candidates)))))
+
+(defun lsp-completion--exit-fn (candidate _status &optional candidates)
+ "Exit function of `completion-at-point'.
+CANDIDATE is the selected completion item.
+Others: CANDIDATES"
+ (unwind-protect
+ (-let* ((candidate (if (plist-member (text-properties-at 0 candidate)
+ 'lsp-completion-item)
+ candidate
+ (cl-find candidate (funcall candidates) :test #'equal)))
+ ((&plist 'lsp-completion-item item
+ 'lsp-completion-start-point start-point
+ 'lsp-completion-markers markers
+ 'lsp-completion-prefix prefix)
+ (text-properties-at 0 candidate))
+ ((&CompletionItem? :label :insert-text? :text-edit? :insert-text-format?
+ :additional-text-edits? :insert-text-mode? :command?)
+ item))
+ (cond
+ (text-edit?
+ (apply #'delete-region markers)
+ (insert prefix)
+ (pcase text-edit?
+ ((TextEdit) (lsp--apply-text-edit text-edit?))
+ ((InsertReplaceEdit :insert :replace :new-text)
+ (lsp--apply-text-edit
+ (lsp-make-text-edit
+ :new-text new-text
+ :range (if (or (and current-prefix-arg (eq lsp-completion-default-behaviour :replace))
+ (and (not current-prefix-arg) (eq lsp-completion-default-behaviour :insert)))
+ insert
+ replace))))))
+ ((or (unless (lsp-falsy? insert-text?) insert-text?) label)
+ (apply #'delete-region markers)
+ (insert prefix)
+ (delete-region start-point (point))
+ (insert (or (unless (lsp-falsy? insert-text?) insert-text?) label))))
+
+ (lsp--indent-lines start-point (point) insert-text-mode?)
+ (when (equal insert-text-format? lsp/insert-text-format-snippet)
+ (lsp--expand-snippet (buffer-substring start-point (point))
+ start-point
+ (point)))
+
+ (when lsp-completion-enable-additional-text-edit
+ (if (or (get-text-property 0 'lsp-completion-resolved candidate)
+ (not (seq-empty-p additional-text-edits?)))
+ (lsp--apply-text-edits additional-text-edits? 'completion)
+ (-let [(callback cleanup-fn) (lsp--create-apply-text-edits-handlers)]
+ (lsp-completion--resolve-async
+ item
+ (-compose callback #'lsp:completion-item-additional-text-edits?)
+ cleanup-fn))))
+
+ (if (or (get-text-property 0 'lsp-completion-resolved candidate)
+ command?)
+ (when command? (lsp--execute-command command?))
+ (lsp-completion--resolve-async
+ item
+ (-lambda ((&CompletionItem? :command?))
+ (when command? (lsp--execute-command command?)))))
+
+ (when (and (or
+ (equal lsp-signature-auto-activate t)
+ (memq :after-completion lsp-signature-auto-activate)
+ (and (memq :on-trigger-char lsp-signature-auto-activate)
+ (-when-let ((&SignatureHelpOptions? :trigger-characters?)
+ (lsp--capability :signatureHelpProvider))
+ (lsp-completion--looking-back-trigger-characterp
+ trigger-characters?))))
+ (lsp-feature? "textDocument/signatureHelp"))
+ (lsp-signature-activate))
+
+ (setq-local lsp-inhibit-lsp-hooks nil))
+ (lsp-completion--clear-cache)))
+
+(defun lsp-completion--regex-fuz (str)
+ "Build a regex sequence from STR. Insert .* between each char."
+ (apply #'concat
+ (cl-mapcar
+ #'concat
+ (cons "" (cdr (seq-map (lambda (c) (format "[^%c]*" c)) str)))
+ (seq-map (lambda (c)
+ (format "\\(%s\\)" (regexp-quote (char-to-string c))))
+ str))))
+
+(defun lsp-completion--fuz-score (query str)
+ "Calculate fuzzy score for STR with query QUERY.
+The return is nil or in range of (0, inf)."
+ (-when-let* ((md (cddr (or (get-text-property 0 'match-data str)
+ (let ((re (lsp-completion--regex-fuz query)))
+ (when (string-match re str)
+ (match-data))))))
+ (start (pop md))
+ (len (length str))
+ ;; To understand how this works, consider these bad ascii(tm)
+ ;; diagrams showing how the pattern "foo" flex-matches
+ ;; "fabrobazo", "fbarbazoo" and "barfoobaz":
+
+ ;; f abr o baz o
+ ;; + --- + --- +
+
+ ;; f barbaz oo
+ ;; + ------ ++
+
+ ;; bar foo baz
+ ;; --- +++ ---
+
+ ;; "+" indicates parts where the pattern matched. A "hole" in
+ ;; the middle of the string is indicated by "-". Note that there
+ ;; are no "holes" near the edges of the string. The completion
+ ;; score is a number bound by ]0..1]: the higher the better and
+ ;; only a perfect match (pattern equals string) will have score
+ ;; 1. The formula takes the form of a quotient. For the
+ ;; numerator, we use the number of +, i.e. the length of the
+ ;; pattern. For the denominator, it first computes
+ ;;
+ ;; hole_i_contrib = 1 + (Li-1)^1.05 for first hole
+ ;; hole_i_contrib = 1 + (Li-1)^0.25 for hole i of length Li
+ ;;
+ ;; The final value for the denominator is then given by:
+ ;;
+ ;; (SUM_across_i(hole_i_contrib) + 1)
+ ;;
+ (score-numerator 0)
+ (score-denominator 0)
+ (last-b -1)
+ (q-ind 0)
+ (update-score
+ (lambda (a b)
+ "Update score variables given match range (A B)."
+ (setq score-numerator (+ score-numerator (- b a)))
+ (unless (= a len)
+ ;; case mis-match will be pushed to near next rank
+ (unless (equal (aref query q-ind) (aref str a))
+ (cl-incf a 0.9))
+ (setq score-denominator
+ (+ score-denominator
+ (if (= a last-b) 0
+ (+ 1 (* (if (< 0 (- a last-b 1)) 1 -1)
+ (expt (abs (- a last-b 1))
+ ;; Give a higher score for match near start
+ (if (eq last-b -1) 0.75 0.25))))))))
+ (setq last-b b))))
+ (while md
+ (funcall update-score start (cl-first md))
+ ;; Due to the way completion regex is constructed, `(eq end (+ start 1))`
+ (cl-incf q-ind)
+ (pop md)
+ (setq start (pop md)))
+ (unless (zerop len)
+ (/ score-numerator (1+ score-denominator) 1.0))))
+
+(defun lsp-completion--fix-resolve-data (item)
+ ;; patch `CompletionItem' for rust-analyzer otherwise resolve will fail
+ ;; see #2675
+ (let ((data (lsp:completion-item-data? item)))
+ (when (lsp-member? data :import_for_trait_assoc_item)
+ (unless (lsp-get data :import_for_trait_assoc_item)
+ (lsp-put data :import_for_trait_assoc_item :json-false)))))
+
+(defun lsp-completion--resolve (item)
+ "Resolve completion ITEM."
+ (cl-assert item nil "Completion item must not be nil")
+ (lsp-completion--fix-resolve-data item)
+ (or (ignore-errors
+ (when (lsp-feature? "completionItem/resolve")
+ (lsp-request "completionItem/resolve" item)))
+ item))
+
+(defun lsp-completion--resolve-async (item callback &optional cleanup-fn)
+ "Resolve completion ITEM asynchronously with CALLBACK.
+The CLEANUP-FN will be called to cleanup."
+ (cl-assert item nil "Completion item must not be nil")
+ (lsp-completion--fix-resolve-data item)
+ (ignore-errors
+ (if (lsp-feature? "completionItem/resolve")
+ (lsp-request-async "completionItem/resolve" item
+ (lambda (result)
+ (funcall callback result)
+ (when cleanup-fn (funcall cleanup-fn)))
+ :error-handler (lambda (err)
+ (when cleanup-fn (funcall cleanup-fn))
+ (error (lsp:json-error-message err)))
+ :cancel-handler cleanup-fn
+ :mode 'alive)
+ (funcall callback item)
+ (when cleanup-fn (funcall cleanup-fn)))))
+
+
+;;;###autoload
+(defun lsp-completion--enable ()
+ "Enable LSP completion support."
+ (when (and lsp-completion-enable
+ (lsp-feature? "textDocument/completion"))
+ (lsp-completion-mode 1)))
+
+(defun lsp-completion--disable ()
+ "Disable LSP completion support."
+ (lsp-completion-mode -1))
+
+;;;###autoload
+(define-minor-mode lsp-completion-mode
+ "Toggle LSP completion support."
+ :group 'lsp-completion
+ :global nil
+ :lighter ""
+ (let ((completion-started-fn (lambda (&rest _)
+ (setq-local lsp-inhibit-lsp-hooks t)))
+ (after-completion-fn (lambda (result)
+ (when (stringp result)
+ (lsp-completion--clear-cache))
+ (setq-local lsp-inhibit-lsp-hooks nil))))
+ (cond
+ (lsp-completion-mode
+ (setq-local completion-at-point-functions nil)
+ (add-hook 'completion-at-point-functions #'lsp-completion-at-point nil t)
+ (setq-local completion-category-defaults
+ (add-to-list 'completion-category-defaults '(lsp-capf (styles basic))))
+
+ (cond
+ ((equal lsp-completion-provider :none))
+ ((and (not (equal lsp-completion-provider :none))
+ (fboundp 'company-mode))
+ (setq-local company-abort-on-unique-match nil)
+ (company-mode 1)
+ (setq-local company-backends (cl-adjoin 'company-capf company-backends :test #'equal)))
+ (t
+ (lsp--warn "Unable to autoconfigure company-mode.")))
+
+ (when (bound-and-true-p company-mode)
+ (add-hook 'company-completion-started-hook
+ completion-started-fn
+ nil
+ t)
+ (add-hook 'company-after-completion-hook
+ after-completion-fn
+ nil
+ t))
+ (add-hook 'lsp-unconfigure-hook #'lsp-completion--disable nil t))
+ (t
+ (remove-hook 'completion-at-point-functions #'lsp-completion-at-point t)
+ (setq-local completion-category-defaults
+ (cl-remove 'lsp-capf completion-category-defaults :key #'cl-first))
+ (remove-hook 'lsp-unconfigure-hook #'lsp-completion--disable t)
+ (when (featurep 'company)
+ (remove-hook 'company-completion-started-hook
+ completion-started-fn
+ t)
+ (remove-hook 'company-after-completion-hook
+ after-completion-fn
+ t))))))
+
+;;;###autoload
+(add-hook 'lsp-configure-hook (lambda ()
+ (when (and lsp-auto-configure
+ lsp-completion-enable)
+ (lsp-completion--enable))))
+
+(lsp-consistency-check lsp-completion)
+
+(provide 'lsp-completion)
+;;; lsp-completion.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-crystal.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-crystal.el
new file mode 100644
index 0000000..f0aca59
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-crystal.el
@@ -0,0 +1,48 @@
+;;; lsp-crystal.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, crystal
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Crystal Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-scry nil
+ "LSP support for Crystal via scry."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/crystal-lang-tools/scry"))
+
+(defcustom lsp-clients-crystal-executable '("scry" "--stdio")
+ "Command to start the scry language server."
+ :group 'lsp-scry
+ :risky t
+ :type 'file)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-crystal-executable)
+ :major-modes '(crystal-mode)
+ :server-id 'scry))
+
+(lsp-consistency-check lsp-crystal)
+
+(provide 'lsp-crystal)
+;;; lsp-crystal.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-csharp.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-csharp.el
new file mode 100644
index 0000000..ea36425
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-csharp.el
@@ -0,0 +1,365 @@
+;;; lsp-csharp.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Jostein Kjønigsen, Saulius Menkevicius
+
+;; Author: Saulius Menkevicius <saulius.menkevicius@fastmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-csharp client
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'gnutls)
+(require 'f)
+
+(defgroup lsp-csharp nil
+ "LSP support for C#, using the Omnisharp Language Server.
+Version 1.34.3 minimum is required."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/OmniSharp/omnisharp-roslyn"))
+
+(defcustom lsp-csharp-server-install-dir
+ (f-join lsp-server-install-dir "omnisharp-roslyn/")
+ "Installation directory for OmniSharp Roslyn server."
+ :group 'lsp-csharp
+ :type 'directory)
+
+(defcustom lsp-csharp-server-path
+ nil
+ "The path to the OmniSharp Roslyn language-server binary.
+Set this if you have the binary installed or have it built yourself."
+ :group 'lsp-csharp
+ :type '(string :tag "Single string value or nil"))
+
+(defcustom lsp-csharp-test-run-buffer-name
+ "*lsp-csharp test run*"
+ "The name of buffer used for outputing lsp-csharp test run results."
+ :group 'lsp-csharp
+ :type 'string)
+
+(defcustom lsp-csharp-solution-file
+ nil
+ "Solution to load when starting the server.
+Usually this is to be set in your .dir-locals.el on the project root directory."
+ :group 'lsp-csharp
+ :type 'string)
+
+(defcustom lsp-csharp-omnisharp-roslyn-download-url
+ (concat "https://github.com/omnisharp/omnisharp-roslyn/releases/latest/download/"
+ (cond ((eq system-type 'windows-nt)
+ ; On Windows we're trying to avoid a crash starting 64bit .NET PE binaries in
+ ; Emacs by using x86 version of omnisharp-roslyn on older (<= 26.4) versions
+ ; of Emacs. See https://lists.nongnu.org/archive/html/bug-gnu-emacs/2017-06/msg00893.html"
+ (if (and (string-match "^x86_64-.*" system-configuration)
+ (version<= "26.4" emacs-version))
+ "omnisharp-win-x64.zip"
+ "omnisharp-win-x86.zip"))
+
+ ((eq system-type 'darwin)
+ "omnisharp-osx.zip")
+
+ ((and (eq system-type 'gnu/linux)
+ (or (eq (string-match "^x86_64" system-configuration) 0)
+ (eq (string-match "^i[3-6]86" system-configuration) 0)))
+ "omnisharp-linux-x64.zip")
+
+ (t "omnisharp-mono.zip")))
+ "Automatic download url for omnisharp-roslyn."
+ :group 'lsp-csharp
+ :type 'string)
+
+(defcustom lsp-csharp-omnisharp-roslyn-store-path
+ (f-join lsp-csharp-server-install-dir "latest" "omnisharp-roslyn.zip")
+ "The path where omnisharp-roslyn .zip archive will be stored."
+ :group 'lsp-csharp
+ :type 'file)
+
+(defcustom lsp-csharp-omnisharp-roslyn-server-dir
+ (f-join lsp-csharp-server-install-dir "latest" "omnisharp-roslyn")
+ "The path where omnisharp-roslyn .zip archive will be extracted."
+ :group 'lsp-csharp
+ :type 'file)
+
+(lsp-dependency
+ 'omnisharp-roslyn
+ `(:download :url lsp-csharp-omnisharp-roslyn-download-url
+ :store-path lsp-csharp-omnisharp-roslyn-store-path))
+
+(defun lsp-csharp--download-server (_client callback error-callback _update?)
+ "Download zip package for omnisharp-roslyn and install it.
+Will invoke CALLBACK on success, ERROR-CALLBACK on error."
+ (lsp-package-ensure
+ 'omnisharp-roslyn
+ (lambda ()
+ (lsp-unzip lsp-csharp-omnisharp-roslyn-store-path
+ lsp-csharp-omnisharp-roslyn-server-dir)
+ (unless (eq system-type 'windows-nt)
+ (let ((run-script (f-join lsp-csharp-omnisharp-roslyn-server-dir "run")))
+ (when (not (f-exists-p run-script))
+ ; create the `run' script when missing (e.g. when server binaries are extracted from omnisharp-mono.zip)
+ ; NOTE: we do not check for presence or version of mono in the system
+ (with-temp-file run-script
+ (insert "#!/bin/bash\n")
+ (insert "BASEDIR=$(dirname \"$0\")\n")
+ (insert "exec mono $BASEDIR/OmniSharp.exe $@\n")))
+ (set-file-modes run-script #o755)))
+ (funcall callback))
+ error-callback))
+
+(defun lsp-csharp--language-server-path ()
+ "Resolve path to use to start the server."
+ (if lsp-csharp-server-path
+ lsp-csharp-server-path
+ (let ((server-dir lsp-csharp-omnisharp-roslyn-server-dir))
+ (when (f-exists? server-dir)
+ (f-join server-dir (cond ((eq system-type 'windows-nt) "OmniSharp.exe")
+ (t "run")))))))
+
+(defun lsp-csharp--language-server-command ()
+ "Resolves path and arguments to use to start the server."
+ (append
+ (list (lsp-csharp--language-server-path) "-lsp")
+ (when lsp-csharp-solution-file (list "-s" (expand-file-name lsp-csharp-solution-file)))))
+
+(lsp-defun lsp-csharp-open-project-file ()
+ "Open corresponding project file (.csproj) for the current file."
+ (interactive)
+ (-let* ((project-info-req (lsp-make-omnisharp-project-information-request :file-name (buffer-file-name)))
+ (project-info (lsp-request "o#/project" project-info-req))
+ ((&omnisharp:ProjectInformation :ms-build-project) project-info)
+ ((&omnisharp:MsBuildProject :path) ms-build-project))
+ (find-file path)))
+
+(defun lsp-csharp--get-buffer-code-elements ()
+ "Retrieve code structure by calling into the /v2/codestructure endpoint.
+Returns :elements from omnisharp:CodeStructureResponse."
+ (-let* ((code-structure (lsp-request "o#/v2/codestructure"
+ (lsp-make-omnisharp-code-structure-request :file-name (buffer-file-name))))
+ ((&omnisharp:CodeStructureResponse :elements) code-structure))
+ elements))
+
+(defun lsp-csharp--inspect-code-elements-recursively (fn elements)
+ "Invoke FN for every omnisharp:CodeElement found recursively in ELEMENTS."
+ (seq-each
+ (lambda (el)
+ (funcall fn el)
+ (-let (((&omnisharp:CodeElement :children) el))
+ (lsp-csharp--inspect-code-elements-recursively fn children)))
+ elements))
+
+(defun lsp-csharp--collect-code-elements-recursively (predicate elements)
+ "Flatten the omnisharp:CodeElement tree in ELEMENTS matching PREDICATE."
+ (let ((results nil))
+ (lsp-csharp--inspect-code-elements-recursively (lambda (el)
+ (when (funcall predicate el)
+ (setq results (cons el results))))
+ elements)
+ results))
+
+(lsp-defun lsp-csharp--l-c-within-range (l c (&omnisharp:Range :start :end))
+ "Determine if L (line) and C (column) are within RANGE."
+ (-let* (((&omnisharp:Point :line start-l :column start-c) start)
+ ((&omnisharp:Point :line end-l :column end-c) end))
+ (or (and (= l start-l) (>= c start-c) (or (> end-l start-l) (<= c end-c)))
+ (and (> l start-l) (< l end-l))
+ (and (= l end-l) (<= c end-c)))))
+
+(defun lsp-csharp--code-element-stack-on-l-c (l c elements)
+ "Return omnisharp:CodeElement stack at L (line) and C (column) in ELEMENTS tree."
+ (when-let ((matching-element (seq-find (lambda (el)
+ (-when-let* (((&omnisharp:CodeElement :ranges) el)
+ ((&omnisharp:RangeList :full?) ranges))
+ (lsp-csharp--l-c-within-range l c full?)))
+ elements)))
+ (-let (((&omnisharp:CodeElement :children) matching-element))
+ (cons matching-element (lsp-csharp--code-element-stack-on-l-c l c children)))))
+
+(defun lsp-csharp--code-element-stack-at-point ()
+ "Return omnisharp:CodeElement stack at point as a list."
+ (let ((pos-line (plist-get (lsp--cur-position) :line))
+ (pos-col (plist-get (lsp--cur-position) :character)))
+ (lsp-csharp--code-element-stack-on-l-c pos-line
+ pos-col
+ (lsp-csharp--get-buffer-code-elements))))
+
+(lsp-defun lsp-csharp--code-element-test-method-p (element)
+ "Return test method name and test framework for a given ELEMENT."
+ (when element
+ (-when-let* (((&omnisharp:CodeElement :properties) element)
+ ((&omnisharp:CodeElementProperties :test-method-name? :test-framework?) properties))
+ (list test-method-name? test-framework?))))
+
+(defun lsp-csharp--reset-test-buffer (present-buffer)
+ "Create new or reuse an existing test result output buffer.
+PRESENT-BUFFER will make the buffer be presented to the user."
+ (with-current-buffer (get-buffer-create lsp-csharp-test-run-buffer-name)
+ (compilation-mode)
+ (read-only-mode)
+ (let ((inhibit-read-only t))
+ (erase-buffer)))
+
+ (when present-buffer
+ (display-buffer lsp-csharp-test-run-buffer-name)))
+
+(defun lsp-csharp--start-tests (test-method-framework test-method-names)
+ "Run test(s) identified by TEST-METHOD-NAMES using TEST-METHOD-FRAMEWORK."
+ (if (and test-method-framework test-method-names)
+ (let ((request-message (lsp-make-omnisharp-run-tests-in-class-request
+ :file-name (buffer-file-name)
+ :test-frameworkname test-method-framework
+ :method-names (vconcat test-method-names))))
+ (lsp-csharp--reset-test-buffer t)
+ (lsp-session-set-metadata "last-test-method-framework" test-method-framework)
+ (lsp-session-set-metadata "last-test-method-names" test-method-names)
+ (lsp-request-async "o#/v2/runtestsinclass"
+ request-message
+ (-lambda ((&omnisharp:RunTestResponse))
+ (message "lsp-csharp: Test run has started"))))
+ (message "lsp-csharp: No test methods to run")))
+
+(defun lsp-csharp--test-message (message)
+ "Emit a MESSAGE to lsp-csharp test run buffer."
+ (when-let ((existing-buffer (get-buffer lsp-csharp-test-run-buffer-name))
+ (inhibit-read-only t))
+ (with-current-buffer existing-buffer
+ (save-excursion
+ (goto-char (point-max))
+ (insert message "\n")))))
+
+(defun lsp-csharp-run-test-at-point ()
+ "Start test run at current point (if any)."
+ (interactive)
+ (let* ((stack (lsp-csharp--code-element-stack-at-point))
+ (element-on-point (car (last stack)))
+ (test-method (lsp-csharp--code-element-test-method-p element-on-point))
+ (test-method-name (car test-method))
+ (test-method-framework (car (cdr test-method))))
+ (lsp-csharp--start-tests test-method-framework (list test-method-name))))
+
+(defun lsp-csharp-run-all-tests-in-buffer ()
+ "Run all test methods in the current buffer."
+ (interactive)
+ (let* ((elements (lsp-csharp--get-buffer-code-elements))
+ (test-methods (lsp-csharp--collect-code-elements-recursively 'lsp-csharp--code-element-test-method-p elements))
+ (test-method-framework (car (cdr (lsp-csharp--code-element-test-method-p (car test-methods)))))
+ (test-method-names (mapcar (lambda (method)
+ (car (lsp-csharp--code-element-test-method-p method)))
+ test-methods)))
+ (lsp-csharp--start-tests test-method-framework test-method-names)))
+
+(defun lsp-csharp-run-test-in-buffer ()
+ "Run selected test in current buffer."
+ (interactive)
+ (when-let* ((elements (lsp-csharp--get-buffer-code-elements))
+ (test-methods (lsp-csharp--collect-code-elements-recursively 'lsp-csharp--code-element-test-method-p elements))
+ (test-method-framework (car (cdr (lsp-csharp--code-element-test-method-p (car test-methods)))))
+ (test-method-names (mapcar (lambda (method)
+ (car (lsp-csharp--code-element-test-method-p method)))
+ test-methods))
+ (selected-test-method-name (lsp--completing-read "Select test:" test-method-names 'identity)))
+ (lsp-csharp--start-tests test-method-framework (list selected-test-method-name))))
+
+(defun lsp-csharp-run-last-tests ()
+ "Re-run test(s) that were run last time."
+ (interactive)
+ (if-let ((last-test-method-framework (lsp-session-get-metadata "last-test-method-framework"))
+ (last-test-method-names (lsp-session-get-metadata "last-test-method-names")))
+ (lsp-csharp--start-tests last-test-method-framework last-test-method-names)
+ (message "lsp-csharp: No test method(s) found to be ran previously on this workspace")))
+
+(lsp-defun lsp-csharp--handle-os-error (_workspace (&omnisharp:ErrorMessage :file-name :text))
+ "Handle the 'o#/error' (interop) notification by displaying a message with lsp-warn."
+ (lsp-warn "%s: %s" file-name text))
+
+(lsp-defun lsp-csharp--handle-os-testmessage (_workspace (&omnisharp:TestMessageEvent :message))
+ "Handle the 'o#/testmessage and display test message on lsp-csharp
+test output buffer."
+ (lsp-csharp--test-message message))
+
+(lsp-defun lsp-csharp--handle-os-testcompleted (_workspace (&omnisharp:DotNetTestResult
+ :method-name
+ :outcome
+ :error-message
+ :error-stack-trace
+ :standard-output
+ :standard-error))
+ "Handle the 'o#/testcompleted' message from the server.
+
+Will display the results of the test on the lsp-csharp test output buffer."
+ (let ((passed (string-equal "passed" outcome)))
+ (lsp-csharp--test-message
+ (format "[%s] %s "
+ (propertize (upcase outcome) 'font-lock-face (if passed 'success 'error))
+ method-name))
+
+ (unless passed
+ (lsp-csharp--test-message error-message)
+
+ (when error-stack-trace
+ (lsp-csharp--test-message error-stack-trace))
+
+ (unless (seq-empty-p standard-output)
+ (lsp-csharp--test-message "STANDARD OUTPUT:")
+ (seq-doseq (stdout-line standard-output)
+ (lsp-csharp--test-message stdout-line)))
+
+ (unless (seq-empty-p standard-error)
+ (lsp-csharp--test-message "STANDARD ERROR:")
+ (seq-doseq (stderr-line standard-error)
+ (lsp-csharp--test-message stderr-line))))))
+
+(lsp-defun lsp-csharp--action-client-find-references ((&Command :arguments?))
+ "Read first argument from ACTION as Location and display xrefs for that location
+using the `textDocument/references' request."
+ (-if-let* (((&Location :uri :range) (lsp-seq-first arguments?))
+ ((&Range :start range-start) range)
+ (find-refs-params (append (lsp--text-document-position-params (list :uri uri) range-start)
+ (list :context (list :includeDeclaration json-false))))
+ (locations-found (lsp-request "textDocument/references" find-refs-params)))
+ (lsp-show-xrefs (lsp--locations-to-xref-items locations-found) nil t)
+ (message "No references found")))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ #'lsp-csharp--language-server-command
+ (lambda ()
+ (when-let ((binary (lsp-csharp--language-server-path)))
+ (f-exists? binary))))
+
+ :major-modes '(csharp-mode csharp-tree-sitter-mode)
+ :server-id 'csharp
+ :action-handlers (ht ("omnisharp/client/findReferences" 'lsp-csharp--action-client-find-references))
+ :notification-handlers (ht ("o#/projectadded" 'ignore)
+ ("o#/projectchanged" 'ignore)
+ ("o#/projectremoved" 'ignore)
+ ("o#/packagerestorestarted" 'ignore)
+ ("o#/msbuildprojectdiagnostics" 'ignore)
+ ("o#/packagerestorefinished" 'ignore)
+ ("o#/unresolveddependencies" 'ignore)
+ ("o#/error" 'lsp-csharp--handle-os-error)
+ ("o#/testmessage" 'lsp-csharp--handle-os-testmessage)
+ ("o#/testcompleted" 'lsp-csharp--handle-os-testcompleted)
+ ("o#/projectconfiguration" 'ignore)
+ ("o#/projectdiagnosticstatus" 'ignore))
+ :download-server-fn #'lsp-csharp--download-server))
+
+(lsp-consistency-check lsp-csharp)
+
+(provide 'lsp-csharp)
+;;; lsp-csharp.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-css.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-css.el
new file mode 100644
index 0000000..2363699
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-css.el
@@ -0,0 +1,254 @@
+;;; lsp-css.el --- CSS language server configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defgroup lsp-css nil
+ "LSP support for CSS."
+ :group 'lsp-mode
+ :link '(url-link
+ "https://github.com/vscode-langservers/vscode-css-languageserver-bin"))
+
+(defcustom lsp-css-experimental-custom-data nil
+ "A list of JSON file paths that define custom CSS data that
+loads custom properties, at directives, pseudo classes /
+elements."
+ :type '(repeat string))
+
+(defcustom lsp-css-completion-trigger-property-value-completion t
+ "By default, VS Code triggers property value completion after
+selecting a CSS property. Use this setting to disable this
+behavior."
+ :type 'boolean)
+
+(defcustom lsp-css-validate t
+ "Enables or disables all validations."
+ :type 'boolean)
+
+(defcustom lsp-css-lint-compatible-vendor-prefixes "ignore"
+ "When using a vendor-specific prefix make sure to also include
+all other vendor-specific properties."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-vendor-prefix "warning"
+ "When using a vendor-specific prefix, also include the standard
+property."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-duplicate-properties "ignore"
+ "Do not use duplicate style definitions."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-empty-rules "warning"
+ "Do not use empty rulesets."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-import-statement "ignore"
+ "Import statements do not load in parallel."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-box-model "ignore"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-universal-selector "ignore"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-zero-units "ignore"
+ "No unit for zero needed."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-font-face-properties "warning"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-hex-color-length "error"
+ "Hex colors must consist of three or six hex numbers."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-arguments-in-color-function "error"
+ "Invalid number of parameters."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-unknown-properties "warning"
+ "Unknown property."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-valid-properties nil
+ "A list of properties that are not validated against the
+`unknownProperties` rule."
+ :type '(repeat string))
+
+(defcustom lsp-css-lint-ie-hack "ignore"
+ "IE hacks are only necessary when supporting IE7 and older."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-unknown-vendor-specific-properties "ignore"
+ "Unknown vendor specific property."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-property-ignored-due-to-display "warning"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-important "ignore"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-float "ignore"
+ nil
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-id-selector "ignore"
+ "Selectors should not contain IDs because these rules are too
+tightly coupled with the HTML."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-lint-unknown-at-rules "warning"
+ "Unknown at-rule."
+ :type '(choice
+ (const "ignore")
+ (const "warning")
+ (const "error")))
+
+(defcustom lsp-css-trace-server "off"
+ "Traces the communication between VS Code and the CSS language
+server."
+ :type '(choice
+ (const "off")
+ (const "messages")
+ (const "verbose")))
+
+(lsp-register-custom-settings
+ '(("css.trace.server" lsp-css-trace-server)
+ ("css.lint.unknownAtRules" lsp-css-lint-unknown-at-rules)
+ ("css.lint.idSelector" lsp-css-lint-id-selector)
+ ("css.lint.float" lsp-css-lint-float)
+ ("css.lint.important" lsp-css-lint-important)
+ ("css.lint.propertyIgnoredDueToDisplay" lsp-css-lint-property-ignored-due-to-display)
+ ("css.lint.unknownVendorSpecificProperties" lsp-css-lint-unknown-vendor-specific-properties)
+ ("css.lint.ieHack" lsp-css-lint-ie-hack)
+ ("css.lint.validProperties" lsp-css-lint-valid-properties)
+ ("css.lint.unknownProperties" lsp-css-lint-unknown-properties)
+ ("css.lint.argumentsInColorFunction" lsp-css-lint-arguments-in-color-function)
+ ("css.lint.hexColorLength" lsp-css-lint-hex-color-length)
+ ("css.lint.fontFaceProperties" lsp-css-lint-font-face-properties)
+ ("css.lint.zeroUnits" lsp-css-lint-zero-units)
+ ("css.lint.universalSelector" lsp-css-lint-universal-selector)
+ ("css.lint.boxModel" lsp-css-lint-box-model)
+ ("css.lint.importStatement" lsp-css-lint-import-statement)
+ ("css.lint.emptyRules" lsp-css-lint-empty-rules)
+ ("css.lint.duplicateProperties" lsp-css-lint-duplicate-properties)
+ ("css.lint.vendorPrefix" lsp-css-lint-vendor-prefix)
+ ("css.lint.compatibleVendorPrefixes" lsp-css-lint-compatible-vendor-prefixes)
+ ("css.validate" lsp-css-validate t)
+ ("css.completion.triggerPropertyValueCompletion" lsp-css-completion-trigger-property-value-completion t)
+ ("css.experimental.customData" lsp-css-experimental-custom-data)))
+
+(defun lsp-css--server-command ()
+ "Generate startup command for CSS language server."
+ (list (lsp-package-path 'css-languageserver) "--stdio"))
+
+;;; CSS
+(lsp-defun lsp-css--apply-code-action ((&Command :arguments?))
+ "Apply ACTION as workspace edit command."
+ (lsp--apply-text-edits (cl-caddr arguments?) 'code-action))
+
+(lsp-dependency 'css-languageserver
+ '(:system "css-languageserver")
+ '(:npm :package "vscode-css-languageserver-bin"
+ :path "css-languageserver"))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-css--server-command)
+ :activation-fn (lsp-activate-on "css" "scss" "sass")
+ :priority -1
+ :action-handlers (lsp-ht ("_css.applyCodeAction" #'lsp-css--apply-code-action))
+ :server-id 'css-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'css-languageserver callback error-callback))))
+
+(lsp-consistency-check lsp-css)
+
+(provide 'lsp-css)
+;;; lsp-css.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-d.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-d.el
new file mode 100644
index 0000000..f9c7b13
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-d.el
@@ -0,0 +1,37 @@
+;;; lsp-d.el --- lsp-mode dlang integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 lsp-mode maintainers
+
+;; Author: lsp-mode maintainers
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; client for serve-d
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection "serve-d")
+ :major-modes '(d-mode)
+ :server-id 'serve-d))
+
+(lsp-consistency-check lsp-d)
+
+(provide 'lsp-d)
+;;; lsp-d.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dhall.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dhall.el
new file mode 100644
index 0000000..7b10597
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dhall.el
@@ -0,0 +1,43 @@
+;;; lsp-dhall.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, dhall
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Dhall Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-dhall nil
+ "LSP support for Dhall, using dhall-lsp-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/dhall-lang/dhall-haskell"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection "dhall-lsp-server")
+ :major-modes '(dhall-mode)
+ :priority -1
+ :server-id 'dhallls))
+
+(lsp-consistency-check lsp-dhall)
+
+(provide 'lsp-dhall)
+;;; lsp-dhall.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-diagnostics.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-diagnostics.el
new file mode 100644
index 0000000..ac1512d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-diagnostics.el
@@ -0,0 +1,369 @@
+;;; lsp-diagnostics.el --- LSP diagnostics integration -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP diagnostics integration
+;;
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-diagnostics nil
+ "LSP support for diagnostics"
+ :prefix "lsp-disagnostics-"
+ :group 'lsp-mode
+ :tag "LSP Diagnostics")
+
+;;;###autoload
+(define-obsolete-variable-alias 'lsp-diagnostic-package
+ 'lsp-diagnostics-provider "lsp-mode 7.0.1")
+
+(defcustom lsp-diagnostics-provider :auto
+ "The checker backend provider."
+ :type
+ '(choice
+ (const :tag "Pick flycheck if present and fallback to flymake" :auto)
+ (const :tag "Pick flycheck" :flycheck)
+ (const :tag "Pick flymake" :flymake)
+ (const :tag "Use neither flymake nor lsp" :none)
+ (const :tag "Prefer flymake" t)
+ (const :tag "Prefer flycheck" nil))
+ :group 'lsp-diagnostics
+ :package-version '(lsp-mode . "6.3"))
+
+;;;###autoload
+(define-obsolete-variable-alias 'lsp-flycheck-default-level
+ 'lsp-diagnostics-flycheck-default-level "lsp-mode 7.0.1")
+
+(defcustom lsp-diagnostics-flycheck-default-level 'error
+ "Error level to use when the server does not report back a diagnostic level."
+ :type '(choice
+ (const error)
+ (const warning)
+ (const info))
+ :group 'lsp-diagnostics)
+
+(defcustom lsp-diagnostics-attributes
+ `((unnecessary :foreground "gray")
+ (deprecated :strike-through t))
+ "The Attributes used on the diagnostics.
+List containing (tag attributes) where tag is the LSP diagnostic tag and
+attributes is a `plist' containing face attributes which will be applied
+on top the flycheck face for that error level."
+ :type '(repeat list)
+ :group 'lsp-diagnostics)
+
+(defcustom lsp-diagnostics-disabled-modes nil
+ "A list of major models for which `lsp-diagnostics-mode' should be disabled."
+ :type '(repeat symbol)
+ :group 'lsp-diagnostics
+ :package-version '(lsp-mode . "7.1"))
+
+;; Flycheck integration
+
+(declare-function flycheck-mode "ext:flycheck")
+(declare-function flycheck-define-generic-checker
+ "ext:flycheck" (symbol docstring &rest properties))
+(declare-function flycheck-error-new "ext:flycheck" t t)
+(declare-function flycheck-error-message "ext:flycheck" (err) t)
+(declare-function flycheck-define-error-level "ext:flycheck" (level &rest properties))
+(declare-function flycheck-buffer "ext:flycheck")
+(declare-function flycheck-valid-checker-p "ext:flycheck")
+(declare-function flycheck-stop "ext:flycheck")
+
+(defvar flycheck-mode)
+(defvar flycheck-check-syntax-automatically)
+(defvar flycheck-checker)
+(defvar flycheck-checkers)
+
+
+(defvar-local lsp-diagnostics--flycheck-enabled nil
+ "True when lsp diagnostics flycheck integration has been enabled in this buffer.")
+
+(defvar-local lsp-diagnostics--flycheck-checker nil
+ "The value of flycheck-checker before lsp diagnostics was activated.")
+
+(defun lsp-diagnostics--flycheck-level (flycheck-level tags)
+ "Generate flycheck level from the original FLYCHECK-LEVEL (e.
+g. `error', `warning') and list of LSP TAGS."
+ (let ((name (format "lsp-flycheck-%s-%s"
+ flycheck-level
+ (mapconcat #'symbol-name tags "-"))))
+ (or (intern-soft name)
+ (let* ((face (--doto (intern (format "lsp-%s-face" name))
+ (copy-face (-> flycheck-level
+ (get 'flycheck-overlay-category)
+ (get 'face))
+ it)
+ (mapc (lambda (tag)
+ (apply #'set-face-attribute it nil
+ (cl-rest (assoc tag lsp-diagnostics-attributes))))
+ tags)))
+ (category (--doto (intern (format "lsp-%s-category" name))
+ (setf (get it 'face) face
+ (get it 'priority) 100)))
+ (new-level (intern name))
+ (bitmap (or (get flycheck-level 'flycheck-fringe-bitmaps)
+ (get flycheck-level 'flycheck-fringe-bitmap-double-arrow))))
+ (flycheck-define-error-level new-level
+ :severity (get flycheck-level 'flycheck-error-severity)
+ :compilation-level (get flycheck-level 'flycheck-compilation-level)
+ :overlay-category category
+ :fringe-bitmap bitmap
+ :fringe-face (get flycheck-level 'flycheck-fringe-face)
+ :error-list-face face)
+ new-level))))
+
+(defun lsp-diagnostics--flycheck-calculate-level (severity tags)
+ "Calculate flycheck level by SEVERITY and TAGS."
+ (let ((level (pcase severity
+ (1 'error)
+ (2 'warning)
+ (3 'info)
+ (4 'info)
+ (_ lsp-flycheck-default-level)))
+ ;; materialize only first tag.
+ (tags (seq-map (lambda (tag)
+ (cond
+ ((= tag lsp/diagnostic-tag-unnecessary) 'unnecessary)
+ ((= tag lsp/diagnostic-tag-deprecated) 'deprecated)))
+ tags)))
+ (if tags
+ (lsp-diagnostics--flycheck-level level tags)
+ level)))
+
+(defun lsp-diagnostics--flycheck-start (checker callback)
+ "Start an LSP syntax check with CHECKER.
+
+CALLBACK is the status callback passed by Flycheck."
+
+ (remove-hook 'lsp-on-idle-hook #'lsp-diagnostics--flycheck-buffer t)
+
+ (->> (lsp--get-buffer-diagnostics)
+ (-map (-lambda ((&Diagnostic :message :severity? :tags? :code? :source?
+ :range (&Range :start (&Position :line start-line
+ :character start-character)
+ :end (&Position :line end-line
+ :character end-character))))
+ (flycheck-error-new
+ :buffer (current-buffer)
+ :checker checker
+ :filename buffer-file-name
+ :message message
+ :level (lsp-diagnostics--flycheck-calculate-level severity? tags?)
+ :id code?
+ :group source?
+ :line (lsp-translate-line (1+ start-line))
+ :column (1+ (lsp-translate-column start-character))
+ :end-line (lsp-translate-line (1+ end-line))
+ :end-column (1+ (lsp-translate-column end-character)))))
+ (funcall callback 'finished)))
+
+(defun lsp-diagnostics--flycheck-buffer ()
+ "Trigger flyckeck on buffer."
+ (remove-hook 'lsp-on-idle-hook #'lsp-diagnostics--flycheck-buffer t)
+ (flycheck-buffer))
+
+(defun lsp-diagnostics--flycheck-report ()
+ "Report flycheck.
+This callback is invoked when new diagnostics are received
+from the language server."
+ (when (and (or (memq 'idle-change flycheck-check-syntax-automatically)
+ (and (memq 'save flycheck-check-syntax-automatically)
+ (not (buffer-modified-p))))
+ lsp--cur-workspace)
+ ;; make sure diagnostics are published even if the diagnostics
+ ;; have been received after idle-change has been triggered
+ (->> lsp--cur-workspace
+ (lsp--workspace-buffers)
+ (mapc (lambda (buffer)
+ (when (and (lsp-buffer-live-p buffer)
+ (or
+ (not (bufferp buffer))
+ (and (get-buffer-window buffer)
+ (not (-contains? (buffer-local-value 'lsp-on-idle-hook buffer)
+ 'lsp-diagnostics--flycheck-buffer)))))
+ (lsp-with-current-buffer buffer
+ (add-hook 'lsp-on-idle-hook #'lsp-diagnostics--flycheck-buffer nil t)
+ (lsp--idle-reschedule (current-buffer)))))))))
+
+(cl-defgeneric lsp-diagnostics-flycheck-error-explainer (e _server-id)
+ "Explain a `flycheck-error' E in a generic way depending on the SERVER-ID."
+ (flycheck-error-message e))
+
+(defvar lsp-diagnostics-mode) ;; properly defined by define-minor-mode below
+
+;;;###autoload
+(defun lsp-diagnostics-lsp-checker-if-needed ()
+ (unless (flycheck-valid-checker-p 'lsp)
+ (flycheck-define-generic-checker 'lsp
+ "A syntax checker using the Language Server Protocol (LSP)
+provided by lsp-mode.
+See https://github.com/emacs-lsp/lsp-mode."
+ :start #'lsp-diagnostics--flycheck-start
+ :modes '(lsp-placeholder-mode) ;; placeholder
+ :predicate (lambda () lsp-diagnostics-mode)
+ :error-explainer (lambda (e)
+ (lsp-diagnostics-flycheck-error-explainer
+ e (lsp--workspace-server-id (car-safe (lsp-workspaces))))))))
+
+(defun lsp-diagnostics-flycheck-enable (&rest _)
+ "Enable flycheck integration for the current buffer."
+ (require 'flycheck)
+ (lsp-diagnostics-lsp-checker-if-needed)
+ (and (not lsp-diagnostics--flycheck-enabled)
+ (not (eq flycheck-checker 'lsp))
+ (setq lsp-diagnostics--flycheck-checker flycheck-checker))
+ (setq-local lsp-diagnostics--flycheck-enabled t)
+ (flycheck-mode 1)
+ (flycheck-stop)
+ (setq-local flycheck-checker 'lsp)
+ (lsp-flycheck-add-mode major-mode)
+ (add-to-list 'flycheck-checkers 'lsp)
+ (add-hook 'lsp-diagnostics-updated-hook #'lsp-diagnostics--flycheck-report nil t)
+ (add-hook 'lsp-managed-mode-hook #'lsp-diagnostics--flycheck-report nil t))
+
+(defun lsp-diagnostics-flycheck-disable ()
+ "Disable flycheck integration for the current buffer is it was enabled."
+ (when lsp-diagnostics--flycheck-enabled
+ (flycheck-stop)
+ (when (eq flycheck-checker 'lsp)
+ (setq-local flycheck-checker lsp-diagnostics--flycheck-checker))
+ (setq lsp-diagnostics--flycheck-checker nil)
+ (setq-local lsp-diagnostics--flycheck-enabled nil)
+ (when flycheck-mode
+ (flycheck-mode 1))))
+
+;; Flymake integration
+
+(declare-function flymake-mode "ext:flymake")
+(declare-function flymake-make-diagnostic "ext:flymake")
+(declare-function flymake-diag-region "ext:flymake")
+
+(defvar flymake-diagnostic-functions)
+(defvar flymake-mode)
+(defvar-local lsp-diagnostics--flymake-report-fn nil)
+
+(defun lsp-diagnostics--flymake-setup ()
+ "Setup flymake."
+ (setq lsp-diagnostics--flymake-report-fn nil)
+ (add-hook 'flymake-diagnostic-functions 'lsp-diagnostics--flymake-backend nil t)
+ (add-hook 'lsp-diagnostics-updated-hook 'lsp-diagnostics--flymake-after-diagnostics nil t)
+ (flymake-mode 1))
+
+(defun lsp-diagnostics--flymake-after-diagnostics ()
+ "Handler for `lsp-diagnostics-updated-hook'."
+ (cond
+ ((and lsp-diagnostics--flymake-report-fn flymake-mode)
+ (lsp-diagnostics--flymake-update-diagnostics))
+ ((not flymake-mode)
+ (setq lsp-diagnostics--flymake-report-fn nil))))
+
+(defun lsp-diagnostics--flymake-backend (report-fn &rest _args)
+ "Flymake backend using REPORT-FN."
+ (let ((first-run (null lsp-diagnostics--flymake-report-fn)))
+ (setq lsp-diagnostics--flymake-report-fn report-fn)
+ (when first-run
+ (lsp-diagnostics--flymake-update-diagnostics))))
+
+(defun lsp-diagnostics--flymake-update-diagnostics ()
+ "Report new diagnostics to flymake."
+ (funcall lsp-diagnostics--flymake-report-fn
+ (-some->> (lsp-diagnostics t)
+ (gethash (lsp--fix-path-casing buffer-file-name))
+ (--map (-let* (((&Diagnostic :message :severity?
+ :range (range &as &Range
+ :start (&Position :line start-line :character)
+ :end (&Position :line end-line))) it)
+ ((start . end) (lsp--range-to-region range)))
+ (when (= start end)
+ (if-let ((region (flymake-diag-region (current-buffer)
+ (1+ start-line)
+ character)))
+ (setq start (car region)
+ end (cdr region))
+ (lsp-save-restriction-and-excursion
+ (goto-char (point-min))
+ (setq start (point-at-bol (1+ start-line))
+ end (point-at-eol (1+ end-line))))))
+ (flymake-make-diagnostic (current-buffer)
+ start
+ end
+ (cl-case severity?
+ (1 :error)
+ (2 :warning)
+ (t :note))
+ message))))
+ ;; This :region keyword forces flymake to delete old diagnostics in
+ ;; case the buffer hasn't changed since the last call to the report
+ ;; function. See https://github.com/joaotavora/eglot/issues/159
+ :region (cons (point-min) (point-max))))
+
+
+
+;;;###autoload
+(defun lsp-diagnostics--enable ()
+ "Enable LSP checker support."
+ (when (and (member lsp-diagnostics-provider '(:auto :none :flycheck :flymake t nil))
+ (not (member major-mode lsp-diagnostics-disabled-modes)))
+ (lsp-diagnostics-mode 1)))
+
+(defun lsp-diagnostics--disable ()
+ "Disable LSP checker support."
+ (lsp-diagnostics-mode -1))
+
+;;;###autoload
+(define-minor-mode lsp-diagnostics-mode
+ "Toggle LSP diagnostics integration."
+ :group 'lsp-diagnostics
+ :global nil
+ :lighter ""
+ (cond
+ (lsp-diagnostics-mode
+ (cond
+ ((and (or
+ (and (eq lsp-diagnostics-provider :auto)
+ (functionp 'flycheck-mode))
+ (and (eq lsp-diagnostics-provider :flycheck)
+ (or (functionp 'flycheck-mode)
+ (user-error "The lsp-diagnostics-provider is set to :flycheck but flycheck is not installed?")))
+ ;; legacy
+ (null lsp-diagnostics-provider))
+ (require 'flycheck nil t))
+ (lsp-diagnostics-flycheck-enable))
+ ((or (eq lsp-diagnostics-provider :auto)
+ (eq lsp-diagnostics-provider :flymake)
+ (eq lsp-diagnostics-provider t))
+ (require 'flymake)
+ (lsp-diagnostics--flymake-setup))
+ ((not (eq lsp-diagnostics-provider :none))
+ (lsp--warn "Unable to autoconfigure flycheck/flymake. The diagnostics won't be rendered.")))
+
+ (add-hook 'lsp-unconfigure-hook #'lsp-diagnostics--disable nil t))
+ (t (lsp-diagnostics-flycheck-disable)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-diagnostics--disable t))))
+
+;;;###autoload
+(add-hook 'lsp-configure-hook (lambda ()
+ (when lsp-auto-configure
+ (lsp-diagnostics--enable))))
+
+(lsp-consistency-check lsp-diagnostics)
+
+(provide 'lsp-diagnostics)
+;;; lsp-diagnostics.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dired.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dired.el
new file mode 100644
index 0000000..8b84af7
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dired.el
@@ -0,0 +1,178 @@
+;;; lsp-dired.el --- `lsp-mode' diagnostics integrated into `dired' -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021
+
+;; Author: Alexander Miller <alexanderm@web.de>
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;; `lsp-mode' diagnostics integrated into `dired'
+
+;;; Code:
+
+(require 'dired)
+(require 'pcase)
+(require 'lsp-mode)
+
+(defgroup lsp-dired nil
+ "LSP support for dired"
+ :prefix "lsp-dired-"
+ :group 'lsp-mode
+ :tag "LSP Dired")
+
+(defvar lsp-dired--ranger-adjust nil)
+(with-eval-after-load 'ranger (setf lsp-dired--ranger-adjust t))
+
+(defvar-local lsp-dired-displayed nil
+ "Flags whether icons have been added.")
+
+(defvar-local lsp-dired--covered-subdirs nil
+ "List of subdirs icons were already added for.")
+
+(defun lsp-dired--display ()
+ "Display the icons of files in a dired buffer."
+ (when (and (display-graphic-p)
+ (not lsp-dired-displayed)
+ dired-subdir-alist)
+ (setq-local lsp-dired-displayed t)
+ (pcase-dolist (`(,path . ,pos) dired-subdir-alist)
+ (lsp-dired--insert-for-subdir path pos))))
+
+(defun lsp-dired--insert-for-subdir (path pos)
+ "Display icons for subdir PATH at given POS."
+ (let ((buf (current-buffer)))
+ ;; run the function after current to make sure that we are creating the
+ ;; overlays after `treemacs-icons-dired' has run.
+ (run-with-idle-timer
+ 0.0 nil
+ (lambda ()
+ (unless (and (member path lsp-dired--covered-subdirs)
+ (not (buffer-live-p buf)))
+ (with-current-buffer buf
+ (add-to-list 'lsp-dired--covered-subdirs path)
+ (let (buffer-read-only)
+ (save-excursion
+ (goto-char pos)
+ (forward-line (if lsp-dired--ranger-adjust 1 2))
+ (cl-block :file
+ (while (not (eobp))
+ (if (dired-move-to-filename nil)
+ (let* ((file (dired-get-filename nil t))
+ (bol (progn
+ (point-at-bol)
+ (search-forward-regexp "^[[:space:]]*" (line-end-position) t)
+ (point)))
+ (face (lsp-dired--face-for-path file)))
+ (when face
+ (-doto (make-overlay bol (point-at-eol))
+ (overlay-put 'evaporate t)
+ (overlay-put 'face face))))
+ (cl-return-from :file nil))
+ (forward-line 1)))))))))))
+
+(defface lsp-dired-path-face '((t :inherit font-lock-string-face))
+ "Face used for breadcrumb paths on headerline."
+ :group 'lsp-dired)
+
+(defface lsp-dired-path-error-face
+ '((t :underline (:style wave :color "Red1")))
+ "Face used for breadcrumb paths on headerline when there is an error under that path"
+ :group 'lsp-dired)
+
+(defface lsp-dired-path-warning-face
+ '((t :underline (:style wave :color "Yellow")))
+ "Face used for breadcrumb paths on headerline when there is an warning under that path"
+ :group 'lsp-dired)
+
+(defface lsp-dired-path-info-face
+ '((t :underline (:style wave :color "Green")))
+ "Face used for breadcrumb paths on headerline when there is an info under that path"
+ :group 'lsp-dired)
+
+(defface lsp-dired-path-hint-face
+ '((t :underline (:style wave :color "Green")))
+ "Face used for breadcrumb paths on headerline when there is an hint under that path"
+ :group 'lsp-dired)
+
+(defun lsp-dired--face-for-path (dir)
+ "Calculate the face for DIR."
+ (when-let ((diags (lsp-diagnostics-stats-for (directory-file-name dir))))
+ (cl-labels ((check-severity
+ (severity)
+ (not (zerop (aref diags severity)))))
+ (cond
+ ((check-severity lsp/diagnostic-severity-error)
+ 'lsp-dired-path-error-face)
+ ((check-severity lsp/diagnostic-severity-warning)
+ 'lsp-dired-path-warning-face)
+ ((check-severity lsp/diagnostic-severity-information)
+ 'lsp-dired-path-info-face)
+ ((check-severity lsp/diagnostic-severity-hint)
+ 'lsp-dired-path-hint-face)))))
+
+(defun lsp-dired--insert-subdir-advice (&rest args)
+ "Advice to dired & dired+ insert-subdir commands.
+Will add icons for the subdir in the `car' of ARGS."
+ (let* ((path (car args))
+ (pos (cdr (assoc path dired-subdir-alist))))
+ (when pos
+ (lsp-dired--insert-for-subdir path pos))))
+
+(defun lsp-dired--kill-subdir-advice (&rest _args)
+ "Advice to dired kill-subdir commands.
+Will remove the killed subdir from `lsp-dired--covered-subdirs'."
+ (setf lsp-dired--covered-subdirs (delete (dired-current-directory)
+ lsp-dired--covered-subdirs)))
+
+(defun lsp-dired--reset (&rest _args)
+ "Reset metadata on revert."
+ (setq-local lsp-dired--covered-subdirs nil)
+ (setq-local lsp-dired-displayed nil))
+
+;;;###autoload
+(define-minor-mode lsp-dired-mode
+ "Display `lsp-mode' icons for each file in a dired buffer."
+ :require 'lsp-dired
+ :init-value nil
+ :global t
+ :group 'lsp-dired
+ (cond
+ (lsp-dired-mode
+ (add-hook 'dired-after-readin-hook #'lsp-dired--display)
+ (advice-add 'dired-kill-subdir :before #'lsp-dired--kill-subdir-advice)
+ (advice-add 'dired-insert-subdir :after #'lsp-dired--insert-subdir-advice)
+ (advice-add 'diredp-insert-subdirs :after #'lsp-dired--insert-subdir-advice)
+ (advice-add 'dired-revert :before #'lsp-dired--reset)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (derived-mode-p 'dired-mode)
+ (lsp-dired--display)))))
+ (t
+ (advice-remove 'dired-kill-subdir #'lsp-dired--kill-subdir-advice)
+ (advice-remove 'dired-insert-subdir #'lsp-dired--insert-subdir-advice)
+ (advice-remove 'diredp-insert-subdirs #'lsp-dired--insert-subdir-advice)
+ (advice-remove 'dired-revert #'lsp-dired--reset)
+ (remove-hook 'dired-after-readin-hook #'lsp-dired--display)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (derived-mode-p 'dired-mode)
+ (dired-revert)))))))
+
+
+(lsp-consistency-check lsp-dired)(provide 'lsp-dired)
+
+
+;;; lsp-dired.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dockerfile.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dockerfile.el
new file mode 100644
index 0000000..a095137
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-dockerfile.el
@@ -0,0 +1,66 @@
+;;; lsp-dockerfile.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, dockerfile
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for Dockerfile documents.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+
+;;; Dockerfile
+
+(defgroup lsp-dockerfile nil
+ "Dockerfile LSP client, provided by the Dockerfile Language Server."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/rcjsuen/dockerfile-language-server-nodejs"))
+
+(defcustom lsp-dockerfile-language-server-command
+ '("docker-langserver" "--stdio")
+ "The command that starts the docker language server."
+ :group 'lsp-dockerfile
+ :type '(repeat :tag "List of string values" string))
+
+(lsp-dependency 'docker-langserver
+ '(:system "docker-langserver")
+ '(:npm :package "dockerfile-language-server-nodejs"
+ :path "docker-langserver"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find
+ (cl-first lsp-dockerfile-language-server-command))
+ (lsp-package-path 'docker-langserver))
+ ,@(cl-rest lsp-dockerfile-language-server-command))))
+ :major-modes '(dockerfile-mode)
+ :priority -1
+ :server-id 'dockerfile-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'docker-langserver
+ callback error-callback))))
+
+(lsp-consistency-check lsp-dockerfile)
+
+(provide 'lsp-dockerfile)
+;;; lsp-dockerfile.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elixir.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elixir.el
new file mode 100644
index 0000000..c36579d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elixir.el
@@ -0,0 +1,190 @@
+;;; lsp-elixir.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, elixir
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Elixir Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'ht)
+
+(defcustom lsp-elixir-dialyzer-enabled t
+ "Run ElixirLS's rapid Dialyzer when code is saved."
+ :type 'boolean
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-dialyzer-warn-opts '()
+ "Dialyzer options to enable or disable warnings.
+
+See Dialyzer's documentation for options. Note that the \"race_conditions\"
+option is unsupported"
+ :type '(repeat string)
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-dialyzer-format "dialyxir_long"
+ "Formatter to use for Dialyzer warnings."
+ :type 'string
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-mix-env "test"
+ "Mix environment to use for compilation."
+ :type 'string
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-mix-target nil
+ "Mix target to use for compilation (requires Elixir >= 1.8)."
+ :type 'string
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-project-dir nil
+ "Subdirectory containing Mix project if not in the project root.
+
+If value is `\"\"` then defaults to the workspace rootUri."
+ :type 'string
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-fetch-deps t
+ "Automatically fetch project dependencies when compiling."
+ :type 'boolean
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-suggest-specs t
+ "Suggest @spec annotations inline using Dialyzer's inferred success typings.
+This requires Dialyzer."
+ :type 'boolean
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-signature-after-complete t
+ "Show signature help after confirming autocomplete."
+ :type 'boolean
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defgroup lsp-elixir nil
+ "LSP support for Elixir, using elixir-ls."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/elixir-lsp/elixir-ls"))
+
+(define-obsolete-variable-alias 'lsp-clients-elixir-server-executable 'lsp-elixir-server-command "2021-04-05")
+
+(defcustom lsp-elixir-server-command
+ (if (equal system-type 'windows-nt)
+ '("language_server.bat")
+ '("language_server.sh"))
+ "Command to start elixir-ls.
+
+Leave as default to let `executable-find' search for it."
+ :group 'lsp-elixir
+ :type '(repeat string)
+ :package-version '(lsp-mode . "7.1"))
+
+
+(defconst lsp-elixir-ls-server-dir
+ (f-join lsp-server-install-dir "elixir-ls")
+ "Elixir-ls local server Directory")
+
+(defcustom lsp-elixir-local-server-command
+ (f-join lsp-elixir-ls-server-dir
+ (cl-first lsp-elixir-server-command))
+ "Command to start local elixir-ls binary."
+ :group 'lsp-elixir
+ :type '(repeat string)
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-elixir-enable-test-lenses t
+ "Suggest Tests."
+ :type 'boolean
+ :group 'lsp-elixir
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-elixir--build-test-command (argument)
+ "Builds the test command from the ARGUMENT."
+ (let ((test-name (lsp-get argument :testName))
+ (module (lsp-get argument :module))
+ (describe (lsp-get argument :describe)))
+ (cond (module (concat "\"" "module:" module "\""))
+ ((not test-name) (concat "\"" "describe:" describe "\""))
+ (describe (concat "\"" "test:test " describe " " test-name "\"" ))
+ (t (concat "\"" "test:test " test-name "\"" )))))
+
+(lsp-defun lsp-elixir--run-test ((&Command :arguments?))
+ "Runs tests."
+ (let* ((argument (lsp-seq-first arguments?))
+ (file-path (lsp-get argument :filePath))
+ (test-command (lsp-elixir--build-test-command argument)))
+ (compile
+ (concat "cd " (lsp-workspace-root file-path) " && "
+ "mix test --exclude test --include " test-command " " file-path
+ " --no-color"))
+ file-path))
+
+(lsp-dependency 'elixir-ls
+ '(:system "elixir-ls"))
+
+(lsp-register-custom-settings
+ '(("elixirLS.dialyzerEnabled" lsp-elixir-dialyzer-enabled t)
+ ("elixirLS.dialyzerWarnOpts" lsp-elixir-dialyzer-warn-opts)
+ ("elixirLS.dialyzerFormat" lsp-elixir-dialyzer-format)
+ ("elixirLS.mixEnv" lsp-elixir-mix-env)
+ ("elixirLS.mixTarget" lsp-elixir-mix-target)
+ ("elixirLS.projectDir" lsp-elixir-project-dir)
+ ("elixirLS.fetchDeps" lsp-elixir-fetch-deps t)
+ ("elixirLS.suggestSpecs" lsp-elixir-suggest-specs t)
+ ("elixirLS.signatureAfterComplete" lsp-elixir-signature-after-complete t)
+ ("elixirLS.enableTestLenses" lsp-elixir-enable-test-lenses t)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (when (f-exists? lsp-elixir-local-server-command)
+ lsp-elixir-local-server-command)
+ (or (executable-find
+ (cl-first lsp-elixir-server-command))
+ (lsp-package-path 'elixir-ls))
+ "language_server.bat")
+ ,@(cl-rest lsp-elixir-server-command))))
+ :major-modes '(elixir-mode)
+ :priority -1
+ :server-id 'elixir-ls
+ :action-handlers (ht ("elixir.lens.test.run" 'lsp-elixir--run-test))
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "elixirLS")))
+ (puthash
+ "textDocumentSync"
+ (ht ("save" t)
+ ("change" 2))
+ (lsp--workspace-server-capabilities workspace)))))
+
+(lsp-consistency-check lsp-elixir)
+
+(provide 'lsp-elixir)
+;;; lsp-elixir.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elm.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elm.el
new file mode 100644
index 0000000..55f9f27
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-elm.el
@@ -0,0 +1,137 @@
+;;; lsp-elm.el --- Elm Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Daniel V
+
+;; Author: Daniel V
+;; Keywords: elm lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-elm client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-elm nil
+ "LSP support for the Elm programming language, using the server from https://github.com/elm-tooling/elm-language-server"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/elm-tooling/elm-language-server"))
+
+(defcustom lsp-elm-elm-language-server-path nil
+ "Path for elm-language-server.
+Can be installed globally with: npm i -g @elm-tooling/elm-language-server,
+or manually by cloning the repo and following the installing instructions."
+ :group 'lsp-elm
+ :risky t
+ :type 'file)
+
+(defcustom lsp-elm-trace-server
+ nil
+ "Enable/disable trace logging of client and server communication."
+ :type 'boolean
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-elm-path
+ ""
+ "The path to your elm executable.
+
+Should be empty by default, in that case it will assume the name and try
+to first get it from a local npm installation or a global one. If you
+set it manually it will not try to load from the npm folder."
+ :type 'file
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-elm-format-path
+ ""
+ "The path to your elm-format executable.
+
+Should be empty by default, in that case it will assume the name and try
+to first get it from a local npm installation or a global one. If you
+set it manually it will not try to load from the npm folder."
+ :type 'file
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-elm-test-path
+ ""
+ "The path to your elm-test executable.
+
+Should be empty by default, in that case it will assume the name and try
+to first get it from a local npm installation or a global one. If you
+set it manually it will not try to load from the npm folder."
+ :type 'file
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-disable-elmls-diagnostics
+ nil
+ "Enable/Disable linting diagnostics from the language server."
+ :type 'boolean
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-only-update-diagnostics-on-save
+ nil
+ "Only update compiler diagnostics on save, not on document change."
+ :type 'boolean
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-skip-install-package-confirmation
+ nil
+ "Skip confirmation for the Install Package code action."
+ :type 'boolean
+ :group 'lsp-elm)
+
+(defcustom lsp-elm-server-args
+ '("--stdio")
+ "Arguments to pass to the server."
+ :type '(repeat string)
+ :group 'lsp-elm)
+
+(defun lsp-elm--elm-language-server-command ()
+ "Generate LSP startup command for the Elm Language Server."
+ (cons
+ (or lsp-elm-elm-language-server-path
+ (lsp-package-path 'elm-language-server))
+ lsp-elm-server-args))
+
+(defun lsp-clients-elm--make-init-options ()
+ "Init options for elm-language-server."
+ `(:elmPath ,lsp-elm-elm-path
+ :elmFormatPath ,lsp-elm-elm-format-path
+ :elmTestPath ,lsp-elm-elm-test-path
+ :disableElmLSDiagnostics ,(lsp-json-bool lsp-elm-disable-elmls-diagnostics)
+ :onlyUpdateDiagnosticsOnSave ,(lsp-json-bool lsp-elm-only-update-diagnostics-on-save)
+ :skipInstallPackageConfirmation ,(lsp-json-bool lsp-elm-skip-install-package-confirmation)
+ :trace.server ,(lsp-json-bool lsp-elm-trace-server)))
+
+(lsp-dependency 'elm-language-server
+ '(:system "elm-language-server")
+ '(:npm :package "@elm-tooling/elm-language-server"
+ :path "elm-language-server"))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-elm--elm-language-server-command)
+ :major-modes '(elm-mode)
+ :priority -1
+ :initialization-options #'lsp-clients-elm--make-init-options
+ :server-id 'elm-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'elm-language-server callback error-callback))))
+
+(lsp-consistency-check lsp-elm)
+
+(provide 'lsp-elm)
+;;; lsp-elm.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-erlang.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-erlang.el
new file mode 100644
index 0000000..2deae83
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-erlang.el
@@ -0,0 +1,67 @@
+;;; lsp-erlang.el --- Erlang Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Roberto Aloi
+
+;; Author: Roberto Aloi
+;; Keywords: erlang lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-erlang client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-erlang nil
+ "LSP support for the Erlang programming language, using erlang-ls"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/erlang-ls/erlang_ls"))
+
+(defcustom lsp-erlang-server-path
+ "erlang_ls"
+ "Path to the Erlang Language Server binary."
+ :group 'lsp-erlang
+ :risky t
+ :type 'file)
+
+(defcustom lsp-erlang-server-connection-type
+ 'stdio
+ "Type of connection to use with the Erlang Language Server: tcp or stdio"
+ :group 'lsp-erlang
+ :risky t
+ :type 'symbol)
+
+(defun lsp-erlang-server-start-fun (port)
+ `(,lsp-erlang-server-path
+ "--transport" "tcp"
+ "--port" ,(number-to-string port)))
+
+(defun lsp-erlang-server-connection ()
+ (if (eq lsp-erlang-server-connection-type 'tcp)
+ (lsp-tcp-connection 'lsp-erlang-server-start-fun)
+ (lsp-stdio-connection `(,lsp-erlang-server-path "--transport" "stdio"))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-erlang-server-connection)
+ :major-modes '(erlang-mode)
+ :priority -1
+ :server-id 'erlang-ls))
+
+(lsp-consistency-check lsp-erlang)
+
+(provide 'lsp-erlang)
+;;; lsp-erlang.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-eslint.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-eslint.el
new file mode 100644
index 0000000..1420b45
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-eslint.el
@@ -0,0 +1,355 @@
+;;; lsp-eslint.el --- lsp-mode eslint integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defconst lsp-eslint/status-ok 1)
+(defconst lsp-eslint/status-warn 2)
+(defconst lsp-eslint/status-error 3)
+
+(defgroup lsp-eslint nil
+ "ESlint language server group."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/Microsoft/vscode-eslint"))
+
+(defcustom lsp-eslint-unzipped-path (f-join lsp-server-install-dir "eslint/unzipped")
+ "The path to the file in which `eslint' will be stored."
+ :type 'file
+ :group 'lsp-eslint
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-eslint-server-command `("node"
+ "~/server/out/eslintServer.js"
+ "--stdio")
+ "Command to start eslint server."
+ :risky t
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-enable t
+ "Controls whether eslint is enabled for JavaScript files or not."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-package-manager "npm"
+ "The package manager you use to install node modules."
+ :type '(choice (const :tag "npm" "npm")
+ (const :tag "yarn" "yarn")
+ (const :tag "pnpm" "pnpm")
+ (string :tag "other"))
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-format t
+ "Whether to perform format."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-node-path nil
+ "A path added to NODE_PATH when resolving the eslint module."
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-node "node"
+ "Path to nodejs."
+ :type 'file
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-eslint-options nil
+ "The eslint options object to provide args normally passed to
+ eslint when executed from a command line (see
+ http://eslint.org/docs/developer-guide/nodejs-api#cliengine)."
+ :type 'alist)
+
+(defcustom lsp-eslint-trace-server "off"
+ "Traces the communication between VSCode and the eslint linter service."
+ :type 'string)
+
+(defcustom lsp-eslint-run "onType"
+ "Run the linter on save (onSave) or on type (onType)"
+ :type '(choice (const :tag "onSave" "onSave")
+ (const :tag "onType" "onType"))
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-auto-fix-on-save nil
+ "Turns auto fix on save on or off."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-fix-all-problem-type
+ "all"
+ "Determines which problems are fixed when running the
+source.fixAll code action."
+ :type '(choice
+ (const "all")
+ (const "problems")
+ string)
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-eslint-quiet nil
+ "Turns on quiet mode, which ignores warnings."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-working-directories []
+ ""
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-validate ["javascript" "javascriptreact"]
+ "An array of language ids which should be validated by ESLint"
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-provide-lint-task nil
+ "Controls whether a task for linting the whole workspace will be available."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-lint-task-enable nil
+ "Controls whether a task for linting the whole workspace will be available."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-lint-task-options "."
+ "Command line options applied when running the task for linting the whole
+workspace (see https://eslint.org/docs/user-guide/command-line-interface)."
+ :type 'string
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-runtime nil
+ "The location of the node binary to run ESLint under."
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-code-action-disable-rule-comment '((enable . t) (location . "separateLine"))
+ ""
+ :type 'alist
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-code-action-show-documentation '((enable . t))
+ ""
+ :type 'alist)
+
+(defcustom lsp-eslint-experimental-incremental-sync t
+ "Controls whether the new incremental text document synchronization should
+be used."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-eslint-save-library-choices t
+ "Controls whether to remember choices made to permit or deny ESLint libraries
+from running."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-eslint-library-choices-file (expand-file-name (locate-user-emacs-file ".lsp-eslint-choices"))
+ "The file where choices to permit or deny ESLint libraries from running is
+stored."
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp--find-eslint ()
+ (or
+ (when-let ((workspace-folder (lsp-find-session-folder (lsp-session) default-directory)))
+ (let ((eslint-local-path (f-join workspace-folder "node_modules" ".bin"
+ (if (eq system-type 'windows-nt) "eslint.cmd" "eslint"))))
+ (when (f-exists? eslint-local-path)
+ eslint-local-path)))
+ "eslint"))
+
+(defun lsp-eslint-create-default-configuration ()
+ "Create default eslint configuration."
+ (interactive)
+ (unless (lsp-session-folders (lsp-session))
+ (user-error "There are no workspace folders"))
+ (pcase (->> (lsp-session)
+ lsp-session-folders
+ (-filter (lambda (dir)
+ (-none?
+ (lambda (file) (f-exists? (f-join dir file)))
+ '(".eslintrc.js" ".eslintrc.yaml" ".eslintrc.yml" ".eslintrc" ".eslintrc.json")))))
+ (`nil (user-error "All workspace folders contain eslint configuration"))
+ (folders (let ((default-directory (completing-read "Select project folder: " folders nil t)))
+ (async-shell-command (format "%s --init" (lsp--find-eslint)))))))
+
+(lsp-defun lsp-eslint-status-handler (workspace (&eslint:StatusParams :state))
+ (setf (lsp--workspace-status-string workspace)
+ (propertize "ESLint"
+ 'face (cond
+ ((eq state lsp-eslint/status-error) 'error)
+ ((eq state lsp-eslint/status-warn) 'warn)
+ (t 'success)))))
+
+(lsp-defun lsp-eslint--configuration (_workspace (&ConfigurationParams :items))
+ (->> items
+ (seq-map (-lambda ((&ConfigurationItem :scope-uri?))
+ (-when-let* ((file (lsp--uri-to-path scope-uri?))
+ (buffer (find-buffer-visiting file))
+ (workspace-folder (lsp-find-session-folder (lsp-session) file)))
+ (with-current-buffer buffer
+ (list :validate "probe"
+ :packageManager lsp-eslint-package-manager
+ :codeActionOnSave (list :enable t
+ :mode lsp-eslint-fix-all-problem-type)
+ :format (lsp-json-bool lsp-eslint-format)
+ :options (or lsp-eslint-options (ht))
+ :run (or lsp-eslint-run "onType")
+ :nodePath lsp-eslint-node-path
+ :onIgnoredFiles "off"
+ :quiet (lsp-json-bool lsp-eslint-quiet)
+ :workspaceFolder (list :uri (lsp--path-to-uri workspace-folder)
+ :name (f-filename workspace-folder))
+ :codeAction (list
+ :disableRuleComment (or lsp-eslint-code-action-disable-rule-comment
+ (list :enable t
+ :location "separateLine"))
+ :showDocumentation (or lsp-eslint-code-action-show-documentation
+ (list :enable t))))))))
+ (apply #'vector)))
+
+(lsp-defun lsp-eslint--open-doc (_workspace (&eslint:OpenESLintDocParams :url))
+ "Open documentation."
+ (browse-url url))
+
+(defun lsp-eslint-apply-all-fixes ()
+ "Apply all autofixes in the current buffer."
+ (interactive)
+ (lsp-send-execute-command "eslint.applyAllFixes" (vector (lsp--versioned-text-document-identifier))))
+
+;; XXX: replace with `lsp-make-interactive-code-action' macro
+;; (lsp-make-interactive-code-action eslint-fix-all "source.fixAll.eslint")
+
+(defun lsp-eslint-fix-all ()
+ "Perform the source.fixAll.eslint code action, if available."
+ (interactive)
+ (condition-case nil
+ (lsp-execute-code-action-by-kind "source.fixAll.eslint")
+ (lsp-no-code-actions
+ (when (called-interactively-p 'any)
+ (lsp--info "source.fixAll.eslint action not available")))))
+
+(defun lsp-eslint-server-command ()
+ (if (lsp-eslint-server-exists? lsp-eslint-server-command)
+ lsp-eslint-server-command
+ `(,lsp-eslint-node ,(f-join lsp-eslint-unzipped-path
+ "extension/server/out/eslintServer.js")
+ "--stdio")))
+
+(defun lsp-eslint-server-exists? (eslint-server-command)
+ (let* ((command-name (f-base (f-filename (cl-first eslint-server-command))))
+ (first-argument (cl-second eslint-server-command))
+ (first-argument-exist (and first-argument (file-exists-p first-argument))))
+ (if (equal command-name lsp-eslint-node)
+ first-argument-exist
+ (executable-find (cl-first eslint-server-command)))))
+
+(defvar lsp-eslint--stored-libraries (ht)
+ "Hash table defining if a given path to an ESLint library is allowed to run.
+If the value for a key is 4, it will be allowed. If it is 1, it will not. If a
+value does not exist for the key, or the value is nil, the user will be prompted
+to allow or deny it.")
+
+(when (and (file-exists-p lsp-eslint-library-choices-file)
+ lsp-eslint-save-library-choices)
+ (setq lsp-eslint--stored-libraries (lsp--read-from-file lsp-eslint-library-choices-file)))
+
+(lsp-defun lsp-eslint--confirm-local (_workspace (&eslint:ConfirmExecutionParams :library-path) callback)
+ (if-let ((option-alist '(("Always" 4 . t)
+ ("Yes" 4 . nil)
+ ("No" 1 . nil)
+ ("Never" 1 . t)))
+ (remembered-answer (gethash library-path lsp-eslint--stored-libraries)))
+ (funcall callback remembered-answer)
+ (lsp-ask-question
+ (format "Allow lsp-mode to execute %s?" library-path)
+ (mapcar 'car option-alist)
+ (lambda (response)
+ (let ((option (cdr (assoc response option-alist))))
+ (when (cdr option)
+ (puthash library-path (car option) lsp-eslint--stored-libraries)
+ (when lsp-eslint-save-library-choices
+ (lsp--persist lsp-eslint-library-choices-file lsp-eslint--stored-libraries)))
+ (funcall callback (car option)))))))
+
+(defun lsp-eslint--probe-failed (_workspace _message)
+ "Called when the server detects a misconfiguration in ESLint."
+ (lsp--error "ESLint is not configured correctly. Please ensure your eslintrc is set up for the languages you are using."))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection
+ (lsp-stdio-connection
+ (lambda () (lsp-eslint-server-command))
+ (lambda () (lsp-eslint-server-exists? (lsp-eslint-server-command))))
+ :activation-fn (lambda (filename &optional _)
+ (when lsp-eslint-enable
+ (or (string-match-p (rx (one-or-more anything) "."
+ (or "ts" "js" "jsx" "tsx" "html" "vue")eos)
+ filename)
+ (derived-mode-p 'js-mode 'js2-mode 'typescript-mode 'html-mode))))
+ :priority -1
+ :completion-in-comments? t
+ :add-on? t
+ :multi-root t
+ :notification-handlers (ht ("eslint/status" #'lsp-eslint-status-handler))
+ :request-handlers (ht ("workspace/configuration" #'lsp-eslint--configuration)
+ ("eslint/openDoc" #'lsp-eslint--open-doc)
+ ("eslint/probeFailed" #'lsp-eslint--probe-failed))
+ :async-request-handlers (ht ("eslint/confirmESLintExecution" #'lsp-eslint--confirm-local))
+ :server-id 'eslint
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--server-register-capability
+ (lsp-make-registration
+ :id "random-id"
+ :method "workspace/didChangeWatchedFiles"
+ :register-options? (lsp-make-did-change-watched-files-registration-options
+ :watchers
+ `[,(lsp-make-file-system-watcher
+ :glob-pattern "**/.eslintr{c.js,c.yaml,c.yml,c,c.json}")
+ ,(lsp-make-file-system-watcher
+ :glob-pattern "**/.eslintignore")
+ ,(lsp-make-file-system-watcher
+ :glob-pattern "**/package.json")])))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (let ((tmp-zip (make-temp-file "ext" nil ".zip")))
+ (delete-file tmp-zip)
+ (lsp-download-install
+ (lambda (&rest _)
+ (condition-case err
+ (progn
+ (lsp-unzip tmp-zip lsp-eslint-unzipped-path)
+ (funcall callback))
+ (error (funcall error-callback err))))
+ error-callback
+ :url (lsp-vscode-extension-url "dbaeumer" "vscode-eslint" "2.1.14")
+ :store-path tmp-zip)))))
+
+(lsp-consistency-check lsp-eslint)
+
+(provide 'lsp-eslint)
+;;; lsp-eslint.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fortran.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fortran.el
new file mode 100644
index 0000000..c9ffb7a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fortran.el
@@ -0,0 +1,61 @@
+;;; lsp-fortran.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, fortran
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Fortran Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-fortran nil
+ "LSP support for Fortran, using the Fortran Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/hansec/fortran-language-server"))
+
+(defcustom lsp-clients-fortls-executable "fortls"
+ "The fortls executable to use.
+Leave as just the executable name to use the default behavior of
+finding the executable with `exec-path'."
+ :group 'lsp-fortran
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-fortls-args '()
+ "Extra arguments for the fortls executable"
+ :group 'lsp-fortran
+ :risky t
+ :type '(repeat string))
+
+(defun lsp-clients--fortls-command ()
+ "Generate the language server startup command."
+ `(,lsp-clients-fortls-executable,@lsp-clients-fortls-args))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection 'lsp-clients--fortls-command)
+ :major-modes '(f90-mode fortran-mode)
+ :priority -1
+ :server-id 'fortls))
+
+(lsp-consistency-check lsp-fortran)
+
+(provide 'lsp-fortran)
+;;; lsp-fortran.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fsharp.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fsharp.el
new file mode 100644
index 0000000..6552d83
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-fsharp.el
@@ -0,0 +1,305 @@
+;;; lsp-fsharp.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Reed Mullanix
+
+;; Author: Reed Mullanix <reedmullanix@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-fsharp client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-fsharp nil
+ "LSP support for the F# Programming Language, using the FsharpAutoComplete server."
+ :link '(url-link "https://github.com/fsharp/FsAutoComplete")
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-fsharp-server-runtime 'net-core
+ "The .NET runtime to use."
+ :group 'lsp-fsharp
+ :type '(choice (const :tag "Use .Net Core" net-core)
+ (const :tag "Use Mono" mono)
+ (const :tag "Use .Net Framework" net-framework))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-fsharp-server-install-dir (f-join lsp-server-install-dir "fsautocomplete/")
+ "Install directory for fsautocomplete server.
+The slash is expected at the end."
+ :group 'lsp-fsharp
+ :risky t
+ :type 'directory
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-fsharp-server-args nil
+ "Extra arguments for the F# language server."
+ :type '(repeat string)
+ :group 'lsp-fsharp
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-fsharp-keywords-autocomplete t
+ "Provides keywords in autocomplete list."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-external-autocomplete nil
+ "Provides autocompletion for symbols from not opened namespaces/modules;
+inserts open on accept."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-linter t
+ "Enables FSharpLint integration, provides additional warnings and code
+action fixes."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-union-case-stub-generation t
+ "Enables a code action to generate pattern matching cases."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-union-case-stub-generation-body "failwith \"Not Implemented\""
+ "Defines dummy body used by pattern matching generator."
+ :group 'lsp-fsharp
+ :type 'string
+ :risky t
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-record-stub-generation t
+ "Enables code action to generate record stub."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-record-stub-generation-body "failwith \"Not Implemented\""
+ "Defines dummy body used by record stub generator."
+ :group 'lsp-fsharp
+ :type 'string
+ :risky t
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-interface-stub-generation t
+ "Enables code action to generate an interface stub."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-interface-stub-generation-object-identifier "this"
+ "Defines object identifier used by interface stub generator,
+e.g. `this' or `self'."
+ :group 'lsp-fsharp
+ :type 'string
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-interface-stub-generation-method-body "failwith \"Not Implemented\""
+ "Defines dummy body used by interface stub generator."
+ :group 'lsp-fsharp
+ :type 'string
+ :risky t
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-unused-opens-analyzer t
+ "Enables unused open detection."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-unused-declarations-analyzer t
+ "Enables unused symbol detection."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-simplify-name-analyzer nil
+ "Enables simplify name analyzer and remove redundant qualifier quick fix."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-resolve-namespaces t
+ "Enables resolve namespace quick fix; adds `open' if symbol is from not yet
+opened module/namespace."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-enable-reference-code-lens t
+ "Enables reference count code lenses.
+It is recommended to disable if `--backgorund-service-enabled' is not used."
+ :group 'lsp-fsharp
+ :type 'bool
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-fsharp-auto-workspace-init nil
+ "Enable automatic workspace initialization.
+Do note that this can cause unexpected or challenging behaviors, as solutions
+with test projects are not autoloaded by FSharpAutoComplete."
+ :group 'lsp-fsharp
+ :type 'bool
+ :risky t)
+
+(defun lsp-fsharp--fsac-runtime-cmd ()
+ "Get the command required to run fsautocomplete based off of the
+current runtime."
+ (pcase lsp-fsharp-server-runtime
+ ('net-core "dotnet")
+ ('mono "mono")
+ ('net-framework nil)))
+
+(defun lsp-fsharp--fsac-cmd ()
+ "The location of fsautocomplete executable."
+ (let ((file-ext (if (eq lsp-fsharp-server-runtime 'net-core)
+ ".dll"
+ ".exe")))
+ (expand-file-name (concat "fsautocomplete" file-ext) lsp-fsharp-server-install-dir)))
+
+(defun lsp-fsharp--version-list-latest (lst)
+ "Return latest version from LST (if any)."
+ (->> lst
+ (-map (lambda (x) (car (s-split " " x))))
+ (-filter (lambda (x) (> (length x) 0)))
+ (-sort (lambda (a b) (not (version<= (substring a 1)
+ (substring b 1)))))
+ cl-first))
+
+(defun lsp-fsharp--fetch-json (url)
+ "Retrieve and parse JSON from URL."
+ (with-temp-buffer
+ (url-insert-file-contents url)
+ (let ((json-false :false))
+ (json-read))))
+
+(defun lsp-fsharp--latest-version-from-github ()
+ "Return latest version of the server available from github."
+ (lsp-fsharp--version-list-latest
+ (seq-map (lambda (elt) (s-trim (cdr (assq 'name elt))))
+ (lsp-fsharp--fetch-json "https://api.github.com/repos/fsharp/FsAutoComplete/releases"))))
+
+(defun lsp-fsharp--server-download-url (version)
+ "Return url for .zip file to download for given VERSION, depending on `lsp-fsharp-server-runtime'."
+ (concat "https://github.com/fsharp/FsAutoComplete/releases/download"
+ "/" version
+ "/" (if (eq lsp-fsharp-server-runtime 'net-core)
+ "fsautocomplete.netcore.zip"
+ "fsautocomplete.zip")))
+
+(defun lsp-fsharp--fsac-install (_client callback _error-callback _update?)
+ "Download the latest version of fsautocomplete and extract it to `lsp-fsharp-server-install-dir'."
+ (let* ((temp-file (make-temp-file "fsautocomplete" nil ".zip"))
+ (install-dir-full (expand-file-name lsp-fsharp-server-install-dir))
+ (unzip-script (cond ((executable-find "unzip") (format "mkdir -p %s && unzip -qq %s -d %s" install-dir-full temp-file install-dir-full))
+ ((executable-find "powershell") (format "powershell -noprofile -noninteractive -nologo -ex bypass Expand-Archive -path '%s' -dest '%s'" temp-file install-dir-full))
+ (t (user-error (format "Unable to unzip server - file %s cannot be extracted, please extract it manually" temp-file)))))
+ (latest-version (lsp-fsharp--latest-version-from-github))
+ (server-download-url (lsp-fsharp--server-download-url latest-version)))
+ (url-copy-file server-download-url temp-file t)
+ (shell-command unzip-script)
+ (shell-command (format "%s %s --version" (lsp-fsharp--fsac-runtime-cmd) (lsp-fsharp--fsac-cmd)))
+ (funcall callback)))
+
+(defun lsp-fsharp-update-fsac ()
+ "Update fsautocomplete to the latest version."
+ (interactive)
+ (-let [install-dir (f-expand lsp-fsharp-server-install-dir)]
+ (f-delete install-dir t)
+ (lsp-fsharp--fsac-install nil #'ignore #'lsp--error t)))
+
+(defun lsp-fsharp--make-launch-cmd ()
+ "Build the command required to launch fsautocomplete."
+ (append (list (lsp-fsharp--fsac-runtime-cmd) (lsp-fsharp--fsac-cmd) "--background-service-enabled")
+ lsp-fsharp-server-args))
+
+(defun lsp-fsharp--project-list ()
+ "Get the list of files we need to send to fsharp/workspaceLoad."
+ (let* ((response (lsp-request "fsharp/workspacePeek"
+ `(:directory ,(lsp-workspace-root)
+ :deep 10
+ :excludedDirs ["paket-files" ".git" "packages" "node_modules"])))
+ (data (lsp--read-json (lsp-get response :content)))
+ (found (-> data (lsp-get :Data) (lsp-get :Found)))
+ (directory (seq-find (lambda (d) (equal "directory" (lsp-get d :Type))) found)))
+ (-> directory (lsp-get :Data) (lsp-get :Fsprojs))))
+
+;;;###autoload
+(defun lsp-fsharp--workspace-load (projects)
+ "Load all of the provided PROJECTS."
+ (lsp-request-async "fsharp/workspaceLoad"
+ `(:textDocuments ,(vconcat [] (mapcar (lambda (p) `(:uri ,p)) projects)))
+ (lambda (_)
+ (lsp--info "Workspace Loaded!"))))
+
+(defvar lsp-fsharp--default-init-options (list)
+ "Default init options to be passed to FSharpAutoComplete,
+ updated conditionally by `lsp-fsharp--make-init-options'.")
+
+(defun lsp-fsharp--make-init-options ()
+ "Init options for F#."
+ (-let [opts lsp-fsharp--default-init-options]
+ (if lsp-fsharp-auto-workspace-init
+ (push '(:AutomaticWorkspaceInit . t) opts)
+ opts)))
+
+(lsp-register-custom-settings
+ `(("FSharp.KeywordsAutocomplete" lsp-fsharp-keywords-autocomplete t)
+ ("FSharp.ExternalAutocomplete" lsp-fsharp-external-autocomplete t)
+ ("FSharp.Linter" lsp-fsharp-linter t)
+ ("FSharp.UnionCaseStubGeneration" lsp-fsharp-union-case-stub-generation t)
+ ("FSharp.UnionCaseStubGenerationBody" lsp-fsharp-union-case-stub-generation-body)
+ ("FSharp.RecordStubGeneration" lsp-fsharp-record-stub-generation t)
+ ("FSharp.RecordStubGenerationBody" lsp-fsharp-record-stub-generation-body)
+ ("FSharp.InterfaceStubGeneration" lsp-fsharp-interface-stub-generation t)
+ ("FSharp.InterfaceStubGenerationObjectIdentifier" lsp-fsharp-interface-stub-generation-object-identifier)
+ ("FSharp.InterfaceStubGenerationMethodBody" lsp-fsharp-interface-stub-generation-method-body)
+ ("FSharp.UnusedOpensAnalyzer" lsp-fsharp-unused-opens-analyzer t)
+ ("FSharp.UnusedDeclarationsAnalyzer" lsp-fsharp-unused-declarations-analyzer t)
+ ("FSharp.SimplifyNameAnalyzer" lsp-fsharp-simplify-name-analyzer t)
+ ("FSharp.ResolveNamespaces" lsp-fsharp-resolve-namespaces t)
+ ("FSharp.EnableReferenceCodeLens" lsp-fsharp-enable-reference-code-lens t)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ #'lsp-fsharp--make-launch-cmd
+ (lambda () (f-exists? (lsp-fsharp--fsac-cmd))))
+ :major-modes '(fsharp-mode)
+ :notification-handlers (ht ("fsharp/notifyCancel" #'ignore)
+ ("fsharp/notifyWorkspace" #'ignore)
+ ("fsharp/fileParsed" #'ignore)
+ ("fsharp/notifyWorkspacePeek" #'ignore))
+ :initialization-options 'lsp-fsharp--make-init-options
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ ;; Something needs to be calling lsp--set-configuration
+ (progn
+ (lsp--set-configuration
+ (lsp-configuration-section "fsharp"))
+ (lsp-fsharp--workspace-load
+ (lsp-fsharp--project-list)))))
+ :server-id 'fsac
+ :download-server-fn #'lsp-fsharp--fsac-install))
+
+(lsp-consistency-check lsp-fsharp)
+
+(provide 'lsp-fsharp)
+;;; lsp-fsharp.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-gdscript.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-gdscript.el
new file mode 100644
index 0000000..4a52ec8
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-gdscript.el
@@ -0,0 +1,61 @@
+;;; lsp-gdscript.el --- LSP mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Oliver Frank
+
+;; Author: Oliver Frank <oliverfrank321@gmail.com>
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-gdscript client
+
+;;; Code:
+(require 'lsp-mode)
+
+(defgroup lsp-gdscript nil
+ "LSP support for GDScript, using godot's language server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/godotengine/godot")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-gdscript-port 6008
+ "Port to connect server to"
+ :type 'integer
+ :group 'lsp-gdscript)
+
+(defun lsp-gdscript-tcp-connect-to-port ()
+ (list
+ :connect (lambda (filter sentinel name _environment-fn)
+ (let* ((host "localhost")
+ (port lsp-gdscript-port)
+ (tcp-proc (lsp--open-network-stream host port (concat name "::tcp"))))
+
+ (set-process-query-on-exit-flag tcp-proc nil)
+ (set-process-filter tcp-proc filter)
+ (set-process-sentinel tcp-proc sentinel)
+ (cons tcp-proc tcp-proc)))
+ :test? (lambda () t)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-gdscript-tcp-connect-to-port)
+ :major-modes '(gdscript-mode)
+ :server-id 'gdscript))
+
+
+(lsp-consistency-check lsp-gdscript)(provide 'lsp-gdscript)
+
+
+;;; lsp-gdscript.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-go.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-go.el
new file mode 100644
index 0000000..880a705
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-go.el
@@ -0,0 +1,338 @@
+;;; lsp-go.el --- Go Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Muir Manders
+
+;; Author: Muir Manders <muir@mnd.rs>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-go client
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'lsp-completion)
+
+(defgroup lsp-go nil
+ "LSP support for the Go Programming Language, using the gopls language server."
+ :link '(url-link "https://github.com/golang/tools/blob/master/gopls/README.md")
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.3.2"))
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-server-path
+ 'lsp-go-gopls-server-path
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-gopls-server-path "gopls"
+ "Path to gopls server binary."
+ :type 'string
+ :group 'lsp-go)
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-server-args
+ 'lsp-go-gopls-server-args
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-gopls-server-args nil
+ "Extra CLI arguments for gopls."
+ :type '(repeat string)
+ :group 'lsp-go)
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-use-placeholders
+ 'lsp-go-use-placeholders
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-use-placeholders t
+ "Cause gopls to provide placeholder parameter snippets when
+completing function calls."
+ :type 'boolean
+ :group 'lsp-go)
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-build-flags
+ 'lsp-go-build-flags
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-build-flags []
+ "A vector of flags passed on to the build system when invoked,
+ applied to queries like `go list'."
+ :type 'lsp-string-vector
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "6.2"))
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-env
+ 'lsp-go-env
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-env nil
+ "`gopls' has the unusual ability to set environment variables,
+ intended to affect the behavior of commands invoked by `gopls'
+ on the user's behalf. This variable takes a hash table of env
+ var names to desired values."
+ :type '(alist :key-type (string :tag "env var name") :value-type (string :tag "value"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "6.2"))
+
+(defcustom lsp-go-directory-filters []
+ "A vector of directory filters."
+ :link '(url-link "https://github.com/golang/tools/blob/67e49ef2d0f326051e22a4a55bdf9344ae1a8ed8/gopls/doc/settings.md#directoryfilters-string")
+ :group 'lsp-go
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode "7.1"))
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-hover-kind
+ 'lsp-go-hover-kind
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-hover-kind "SynopsisDocumentation"
+ "`gopls' allows the end user to select the desired amount of
+ documentation returned during e.g. hover and thing-at-point
+ operations."
+ :type '(choice (const "SynopsisDocumentation")
+ (const "NoDocumentation")
+ (const "FullDocumentation")
+ (const "SingleLine")
+ (const "Structured"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "6.2"))
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-available-codelens
+ 'lsp-go-available-codelenses
+ "lsp-mode 7.0.1")
+
+(define-obsolete-variable-alias
+ 'lsp-go-available-codelens
+ 'lsp-go-available-codelenses
+ "lsp-mode 7.0.1")
+
+(defvar lsp-go-available-codelenses
+ '(
+ (gc_details . "Toggle the calculation of gc annotations")
+ (generate . "Run `go generate` for a directory")
+ (regenerate_cgo . "Regenerate cgo definitions")
+ (test . "Run `go test` for a specific set of test or benchmark functions (lgeacy)")
+ (tidy . "Run `go mod tidy` for a module")
+ (upgrade_dependency . "Upgrade a dependency")
+ (vendor . "Runs `go mod vendor' for a module"))
+ "Available codelenses that can be further enabled or disabled
+ through `lsp-go-codelenses'.")
+
+(defun lsp-go--defcustom-available-as-alist-type (alist)
+ "Returns a list suitable for the `:type' field in a `defcustom' used to populate an alist.
+
+The input ALIST has the form `((\"name\" . \"documentation sentence\") [...])'
+
+The returned type provides a tri-state that either:
+ - does not include the element in the alist
+ - sets element to false (actually, :json-false)
+ - sets element to true (actually, t)
+"
+ (let ((list '()))
+ (dolist (v alist)
+ (push `(cons
+ :tag ,(cdr v)
+ (const :format "" ,(car v))
+ (choice (const :tag "Enable" t) (const :tag "Disable" :json-false)))
+ list))
+ (push 'set list)
+ list))
+
+(define-obsolete-variable-alias
+ 'lsp-gopls-codelens
+ 'lsp-go-codelenses
+ "lsp-mode 7.0.1")
+
+(define-obsolete-variable-alias
+ 'lsp-go-codelens
+ 'lsp-go-codelenses
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-codelenses '((gc_details . :json-false)
+ (generate . t)
+ (regenerate_cgo . t)
+ (tidy . t)
+ (upgrade_dependency . t)
+ (test . t)
+ (vendor . t))
+ "Select what codelenses should be enabled or not.
+
+The codelenses can be found at https://github.com/golang/tools/blob/3fa0e8f87c1aae0a9adc2a63af1a1945d16d9359/internal/lsp/source/options.go#L106-L112."
+ :type (lsp-go--defcustom-available-as-alist-type lsp-go-available-codelenses)
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "7.0"))
+
+(define-obsolete-variable-alias
+ 'lsp-clients-go-library-directories
+ 'lsp-go-library-directories
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-library-directories '("/usr")
+ "List of directories which will be considered to be libraries."
+ :group 'lsp-go
+ :risky t
+ :type '(repeat string))
+
+(define-obsolete-variable-alias
+ 'lsp-clients-go-library-directories-include-go-modules
+ 'lsp-go-library-directories-include-go-modules
+ "lsp-mode 7.0.1")
+
+(defcustom lsp-go-library-directories-include-go-modules t
+ "Whether or not $GOPATH/pkg/mod should be included as a library directory."
+ :type 'boolean
+ :group 'lsp-go)
+
+(defun lsp-go--library-default-directories (_workspace)
+ "Calculate go library directories.
+
+If `lsp-go-library-directories-include-go-modules' is non-nil
+and the environment variable GOPATH is set this function will return
+$GOPATH/pkg/mod along with the value of
+`lsp-go-library-directories'."
+ (let ((library-dirs lsp-go-library-directories))
+ (when (and lsp-go-library-directories-include-go-modules
+ (or (and (not (file-remote-p default-directory)) (executable-find "go"))
+ (and (version<= "27.0" emacs-version) (with-no-warnings (executable-find "go" (file-remote-p default-directory))))))
+ (with-temp-buffer
+ (when (zerop (process-file "go" nil t nil "env" "GOPATH"))
+ (setq library-dirs
+ (append
+ library-dirs
+ (list
+ (concat
+ (string-trim-right (buffer-substring (point-min) (point-max)))
+ "/pkg/mod")))))))
+ (if (file-remote-p default-directory)
+ (mapcar (lambda (path) (concat (file-remote-p default-directory) path)) library-dirs)
+ library-dirs)))
+
+(defcustom lsp-go-link-target "godoc.org"
+ "Which website to use for displaying Go documentation."
+ :type '(choice (const "godoc.org")
+ (const "pkg.go.dev")
+ (string :tag "A custom website"))
+ :group 'lsp-go
+ :package-version '(lsp-mode "7.0.1"))
+
+(defcustom lsp-go-links-in-hover t
+ "If non-nil, hover documentation includes links."
+ :type 'boolean
+ :group 'lsp-go
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-use-gofumpt nil
+ "If non-nil, use gofumpt formatting."
+ :type 'boolean
+ :group 'lsp-go
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-goimports-local ""
+ "Equivalent of the goimports -local flag, which puts imports beginning with
+ this string after third-party packages. It should be the prefix of the import
+ path whose imports should be grouped separately."
+ :type 'string
+ :group 'lsp-go
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-analyses nil
+ "Specify analyses that the user would like to enable or disable. A map of the
+ names of analysis passes that should be enabled/disabled. A full list of
+ analyzers that gopls uses can be found at
+ https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md"
+ :type '(alist :key-type (string :tag "analyzer name") :value-type (boolean :tag "value"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-import-shortcut "Both"
+ "Specifies whether import statements should link to documentation or go to
+ definitions."
+ :type '(choice (const "Both")
+ (const "Link")
+ (const "Definition"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-symbol-matcher "Fuzzy"
+ "Sets the algorithm that is used when finding workspace symbols."
+ :type '(choice (const "Fuzzy")
+ (const "CaseInsensitive")
+ (const "CaseSensitive"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "7.1"))
+
+(defcustom lsp-go-symbol-style "Dynamic"
+ "Controls how symbols are qualified in symbol responses.
+
+ 'Dynamic' uses whichever qualifier results in the highest scoring match for
+ the given symbol query. Here a 'qualifier' is any '/' or '.' delimited suffix
+ of the fully qualified symbol. i.e. 'to/pkg.Foo.Field' or just 'Foo.Field'.
+
+ 'Full' is fully qualified symbols, i.e. 'path/to/pkg.Foo.Field'.
+
+ 'Package' is package qualified symbols i.e. 'pkg.Foo.Field'."
+ :type '(choice (const "Dynamic")
+ (const "Full")
+ (const "Package"))
+ :group 'lsp-go
+ :risky t
+ :package-version '(lsp-mode "7.1"))
+
+(lsp-register-custom-settings
+ '(("gopls.usePlaceholders" lsp-go-use-placeholders t)
+ ("gopls.hoverKind" lsp-go-hover-kind)
+ ("gopls.buildFlags" lsp-go-build-flags)
+ ("gopls.env" lsp-go-env)
+ ("gopls.linkTarget" lsp-go-link-target)
+ ("gopls.codelenses" lsp-go-codelenses)
+ ("gopls.linksInHover" lsp-go-links-in-hover t)
+ ("gopls.gofumpt" lsp-go-use-gofumpt t)
+ ("gopls.local" lsp-go-goimports-local)
+ ("gopls.directoryFilters" lsp-go-directory-filters)
+ ("gopls.analyses" lsp-go-analyses)
+ ("gopls.importShortcut" lsp-go-import-shortcut)
+ ("gopls.symbolMatcher" lsp-go-symbol-matcher)
+ ("gopls.symbolStyle" lsp-go-symbol-style)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda () (cons lsp-go-gopls-server-path lsp-go-gopls-server-args)))
+ :major-modes '(go-mode go-dot-mod-mode)
+ :language-id "go"
+ :priority 0
+ :server-id 'gopls
+ :completion-in-comments? t
+ :library-folders-fn #'lsp-go--library-default-directories
+ :after-open-fn (lambda ()
+ ;; https://github.com/golang/tools/commit/b2d8b0336
+ (setq-local lsp-completion-filter-on-incomplete nil))))
+
+(lsp-consistency-check lsp-go)
+
+(provide 'lsp-go)
+;;; lsp-go.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-groovy.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-groovy.el
new file mode 100644
index 0000000..c1fcaaf
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-groovy.el
@@ -0,0 +1,66 @@
+;;; lsp-groovy.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, groovy
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Groovy Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'f)
+
+(defgroup lsp-groovy nil
+ "LSP support for Groovy, using groovy-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/prominic/groovy-language-server"))
+
+(defcustom lsp-groovy-server-file (f-join lsp-server-install-dir "groovy-language-server-all.jar")
+ "JAR file path for groovy-language-server-all.jar."
+ :group 'lsp-groovy
+ :risky t
+ :type 'file)
+
+(defun lsp-groovy--lsp-command ()
+ "Generate LSP startup command."
+ `("java" "-jar" ,(expand-file-name lsp-groovy-server-file)))
+
+(defcustom lsp-groovy-classpath ["/usr/local/opt/groovy/libexec/lib"]
+ "List of paths to Groovy JARs."
+ :group 'lsp-groovy
+ :risky t
+ :type 'lsp-string-vector)
+
+(lsp-register-custom-settings
+ '(("groovy.classpath" lsp-groovy-classpath)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection 'lsp-groovy--lsp-command)
+ :major-modes '(groovy-mode)
+ :priority -1
+ :server-id 'groovy-ls
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "groovy"))))))
+
+(lsp-consistency-check lsp-groovy)
+
+(provide 'lsp-groovy)
+;;; lsp-groovy.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-hack.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-hack.el
new file mode 100644
index 0000000..161659a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-hack.el
@@ -0,0 +1,54 @@
+;;; lsp-xxx.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, hack
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Hack Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-hack nil
+ "LSP support for Hack, using HHVM."
+ :group 'lsp-mode
+ :link '(url-link "https://docs.hhvm.com/hhvm"))
+
+(defcustom lsp-clients-hack-command '("hh_client" "lsp" "--from" "emacs")
+ "Command to start hh_client."
+ :group 'lsp-hack
+ :risky t
+ :type '(repeat string))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-clients-hack-command))
+ :major-modes '(hack-mode)
+ :priority -1
+ :server-id 'hack
+ ;; ignore some unsupported messages from Nuclide
+ :notification-handlers (lsp-ht ("telemetry/event" 'ignore)
+ ("$/cancelRequest" 'ignore))
+ :request-handlers (lsp-ht ("window/showStatus" 'ignore))))
+
+
+(lsp-consistency-check lsp-hack)
+
+(provide 'lsp-hack)
+;;; lsp-hack.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-haxe.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-haxe.el
new file mode 100644
index 0000000..62707be
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-haxe.el
@@ -0,0 +1,226 @@
+;;; lsp-haxe.el --- Haxe Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Yannik Böttcher
+
+;; Author: Yannik Böttcher <yannikboettcher@outlook.de>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-haxe client
+
+;;; Code:
+
+
+;; adapted from lsp-clangd configuration
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defgroup lsp-haxe nil
+ "LSP support for Haxe using the language server provided by vshaxe"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/vshaxe/vshaxe"))
+
+
+;; Haxe ls is executed via node
+(defcustom lsp-clients--haxe-executable "node"
+ "Haxe ls is executed via node."
+ :group 'lsp-haxe
+ :risky t
+ :type 'file)
+
+;; The server.js is being passed to node as an argument
+(defcustom lsp-clients--haxe-server-path (expand-file-name "~/.haxe-language-server/bin/server.js")
+ "The path to the server.js file."
+ :group 'lsp-haxe
+ :risky t
+ :type 'file)
+
+;; Build the actual Haxe ls command.
+(defun lsp-clients--haxe-command ()
+ "Haxe ls startup command."
+ `(,lsp-clients--haxe-executable ,lsp-clients--haxe-server-path))
+
+;; https://github.com/yyoncho/lsp-mode/commit/72186e1adc089d772c87ed8f287eb3333b66bfa7
+;; This is to force the client to send a didChangeConfiguration Message. Without this, the server won't start, https://github.com/vshaxe/vshaxe/issues/328#issuecomment-471809093
+(defcustom lsp-clients--haxe-settings (list :haxe.executable "haxe")
+ "Lsp clients configuration settings."
+ :group 'lsp-haxe
+ :risky t
+ :type '(repeat string))
+
+;; The build spec for the project.
+(defcustom lsp-haxe-hxml "build.hxml"
+ "The compile file for the haxe project."
+ :type 'file
+ :group 'lsp-haxe
+ :package-version '(lsp-mode . "7.0"))
+
+;; https://github.com/emacs-lsp/lsp-mode/blob/150a933694349df960dc8fd7a15e04f5727e6433/lsp-rust.el#L251
+(lsp-defun lsp-clients--haxe-processStart (_workspace (&haxe:ProcessStartNotification :title))
+ "Handle processStart notification. Just logs PARAMS."
+ (lsp-log title))
+
+(defcustom lsp-haxe-executable "haxe"
+ nil
+ :type 'file
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-configurations nil
+ nil
+ :type '(repeat string)
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-display-configurations nil
+ nil
+ :type '(repeat string)
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-display-server nil
+ nil
+ :type 'string
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-display-port "auto"
+ nil
+ :type 'number
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-compilation-server t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-task-presentation
+ '((echo . t)
+ (reveal . "always")
+ (focus . :json-false)
+ (panel . "shared")
+ (showReuseMessage . t)
+ (clear . :json-false))
+ nil
+ :type 'plist
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-code-lens t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-diagnostics t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-server-view nil
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-methods-view nil
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-signature-help-documentation t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-diagnostics-path-filter "${workspaceRoot}"
+ nil
+ :type 'string
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-build-completion-cache t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-enable-completion-cache-warning t
+ nil
+ :type 'boolean
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-code-generation nil
+ nil
+ :type 'string
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-exclude ["zpp_nape"]
+ nil
+ :type '(repeat string)
+ :group 'lsp-haxe)
+
+(defcustom lsp-haxe-postfix-completion nil
+ nil
+ :type 'string
+ :group 'lsp-haxe)
+
+(lsp-register-custom-settings
+ '(("haxe.hxml" lsp-haxe-hxml)
+ ("haxe.postfixCompletion" lsp-haxe-postfix-completion)
+ ("haxe.exclude" lsp-haxe-exclude)
+ ("haxe.codeGeneration" lsp-haxe-code-generation)
+ ("haxe.enableCompletionCacheWarning" lsp-haxe-enable-completion-cache-warning t)
+ ("haxe.buildCompletionCache" lsp-haxe-build-completion-cache t)
+ ("haxe.diagnosticsPathFilter" lsp-haxe-diagnostics-path-filter)
+ ("haxe.enableSignatureHelpDocumentation" lsp-haxe-enable-signature-help-documentation t)
+ ("haxe.enableMethodsView" lsp-haxe-enable-methods-view t)
+ ("haxe.enableServerView" lsp-haxe-enable-server-view t)
+ ("haxe.enableDiagnostics" lsp-haxe-enable-diagnostics t)
+ ("haxe.enableCodeLens" lsp-haxe-enable-code-lens t)
+ ("haxe.taskPresentation" lsp-haxe-task-presentation)
+ ("haxe.enableCompilationServer" lsp-haxe-enable-compilation-server t)
+ ("haxe.displayPort" lsp-haxe-display-port)
+ ("haxe.displayServer" lsp-haxe-display-server)
+ ("haxe.displayConfigurations" lsp-haxe-display-configurations)
+ ("haxe.configurations" lsp-haxe-configurations)
+ ("haxe.executable" lsp-haxe-executable)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-clients--haxe-command)
+ :major-modes '(haxe-mode) ; force didChangeConfiguration message
+ :initialized-fn
+ (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "haxe"))))
+ :priority -1
+ :server-id 'haxe
+ :initialization-options
+ (lambda ()
+ `(:sendMethodResults t
+ :haxelibConfig (:executable "haxelib")
+ :displayServerConfig
+ ( :print (:reusing :json-false :completion :json-false)
+ :arguments []
+ :env nil
+ :path "haxe")
+ :displayArguments [,lsp-haxe-hxml]))
+ :notification-handlers
+ (lsp-ht ("haxe/progressStart" 'lsp-clients--haxe-processStart)
+ ("haxe/progressStop" 'ignore)
+ ("haxe/didDetectOldPreview" 'ignore)
+ ("haxe/didChangeDisplayPort" 'ignore)
+ ("haxe/didRunHaxeMethod" 'ignore)
+ ("haxe/didChangeRequestQueue" 'ignore)
+ ("haxe/cacheBuildFailed" 'ignore))))
+
+(lsp-consistency-check lsp-haxe)
+
+(provide 'lsp-haxe)
+;;; lsp-haxe.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-headerline.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-headerline.el
new file mode 100644
index 0000000..3ed62e5
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-headerline.el
@@ -0,0 +1,473 @@
+;;; lsp-headerline.el --- LSP headerline features -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP headerline features
+;;
+;;; Code:
+
+(require 'lsp-icons)
+(require 'lsp-mode)
+
+(defgroup lsp-headerline nil
+ "LSP support for headerline"
+ :prefix "lsp-headerline-"
+ :group 'lsp-mode
+ :tag "LSP Headerline")
+
+(defcustom lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols)
+ "Segments used in breadcrumb text on headerline."
+ :type '(repeat
+ (choice (const :tag "Include the project name." project)
+ (const :tag "Include the open file name." file)
+ (const :tag "Include the directories up to project." path-up-to-project)
+ (const :tag "Include document symbols if server supports it." symbols)))
+ :group 'lsp-headerline)
+
+(defcustom lsp-headerline-breadcrumb-enable-symbol-numbers nil
+ "Whether to label symbols with numbers on the breadcrumb."
+ :type 'boolean
+ :group 'lsp-headerline)
+
+(defcustom lsp-headerline-breadcrumb-enable-diagnostics t
+ "If non-nil, apply different face on the breadcrumb based on the errors."
+ :type 'boolean
+ :group 'lsp-headerline
+ :package-version '(lsp-mode . "7.1"))
+
+(defface lsp-headerline-breadcrumb-separator-face '((t :inherit shadow :height 0.8))
+ "Face used for breadcrumb separator on headerline."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-path-face '((t :inherit font-lock-string-face))
+ "Face used for breadcrumb paths on headerline."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-path-error-face
+ '((t :underline (:style wave :color "Red1")
+ :inherit lsp-headerline-breadcrumb-path-face))
+ "Face used for breadcrumb paths on headerline when there is an error under that path"
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-path-warning-face
+ '((t :underline (:style wave :color "Yellow")
+ :inherit lsp-headerline-breadcrumb-path-face))
+ "Face used for breadcrumb paths on headerline when there is an warning under that path"
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-path-info-face
+ '((t :underline (:style wave :color "Green")
+ :inherit lsp-headerline-breadcrumb-path-face))
+ "Face used for breadcrumb paths on headerline when there is an info under that path"
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-path-hint-face
+ '((t :underline (:style wave :color "Green")
+ :inherit lsp-headerline-breadcrumb-path-face))
+ "Face used for breadcrumb paths on headerline when there is an hint under that path"
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-project-prefix-face
+ '((t :inherit font-lock-string-face :weight bold))
+ "Face used for breadcrumb prefix on headerline.
+Only if `lsp-headerline-breadcrumb-prefix` is `project-name-only`."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-unknown-project-prefix-face
+ '((t :inherit shadow :weight bold))
+ "Face used for breadcrumb prefix on headerline.
+Only if `lsp-headerline-breadcrumb-prefix` is `project-name-only`."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-symbols-face
+ '((t :inherit font-lock-doc-face :weight bold))
+ "Face used for breadcrumb symbols text on headerline."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-symbols-error-face
+ '((t :inherit lsp-headerline-breadcrumb-symbols-face
+ :underline (:style wave :color "Red1")))
+ "Face used for breadcrumb symbols text on headerline when there
+is an error in symbols range."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-symbols-warning-face
+ '((t :inherit lsp-headerline-breadcrumb-symbols-face
+ :underline (:style wave :color "Yellow")))
+ "Face used for breadcrumb symbols text on headerline when there
+is an warning in symbols range."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-symbols-info-face
+ '((t :inherit lsp-headerline-breadcrumb-symbols-face
+ :underline (:style wave :color "Green")))
+ "Face used for breadcrumb symbols text on headerline when there
+is an info in symbols range."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-symbols-hint-face
+ '((t :inherit lsp-headerline-breadcrumb-symbols-face
+ :underline (:style wave :color "Green")))
+ "Face used for breadcrumb symbols text on headerline when there
+is an hints in symbols range."
+ :group 'lsp-headerline)
+
+(defface lsp-headerline-breadcrumb-deprecated-face
+ '((t :inherit lsp-headerline-breadcrumb-symbols-face
+ :strike-through t))
+ "Face used on breadcrumb deprecated text on modeline."
+ :group 'lsp-headerline)
+
+(defvar-local lsp-headerline--string nil
+ "Holds the current breadcrumb string on headerline.")
+
+(defvar lsp-headerline-arrow nil
+ "Holds the current breadcrumb string on headerline.")
+
+(defvar-local lsp-headerline--path-up-to-project-segments nil
+ "Holds the current breadcrumb path-up-to-project segments for
+caching purposes.")
+
+(defun lsp-headerline--arrow-icon ()
+ "Build the arrow icon for headerline breadcrumb."
+ (or
+ lsp-headerline-arrow
+ (setq lsp-headerline-arrow (lsp-icons-all-the-icons-material-icon
+ "chevron_right"
+ 'lsp-headerline-breadcrumb-separator-face
+ ">"
+ 'headerline-breadcrumb))))
+
+(lsp-defun lsp-headerline--symbol-icon ((&DocumentSymbol :kind))
+ "Build the SYMBOL icon for headerline breadcrumb."
+ (concat (lsp-icons-get-by-symbol-kind kind 'headerline-breadcrumb)
+ " "))
+
+(lsp-defun lsp-headerline--go-to-symbol ((&DocumentSymbol
+ :selection-range (&RangeToPoint :start selection-start)
+ :range (&RangeToPoint :start narrowing-start
+ :end narrowing-end)))
+ "Go to breadcrumb symbol.
+If the buffer is narrowed and the target symbol lies before the
+minimum reachable point in the narrowed buffer, then widen and
+narrow to the outer symbol."
+ (when (buffer-narrowed-p)
+ (narrow-to-region
+ (min (point-min) narrowing-start)
+ (max (point-max) narrowing-end)))
+ (goto-char selection-start))
+
+(lsp-defun lsp-headerline--narrow-to-symbol ((&DocumentSymbol :range (&RangeToPoint :start :end)))
+ "Narrow to breadcrumb symbol range."
+ (narrow-to-region start end))
+
+(defun lsp-headerline--with-action (local-map help-echo-string display-string)
+ "Assign LOCAL-MAP and HELP-ECHO-STRING to the region around the DISPLAY-STRING."
+ (propertize display-string
+ 'mouse-face 'header-line-highlight
+ 'help-echo help-echo-string
+ 'local-map local-map))
+
+(defmacro lsp-headerline--make-mouse-handler (&rest body)
+ "Making mouse event handler.
+Switch to current mouse interacting window before doing BODY."
+ (declare (debug t) (indent 0))
+ `(lambda (event)
+ (interactive "e")
+ (select-window (posn-window (elt event 1)))
+ ,@body))
+
+(defun lsp-headerline--directory-with-action (full-path directory-display-string)
+ "Build action for FULL-PATH and DIRECTORY-DISPLAY-STRING."
+ (lsp-headerline--with-action (let ((map (make-sparse-keymap)))
+ (define-key map [header-line mouse-1]
+ (lsp-headerline--make-mouse-handler
+ (dired full-path)))
+ (define-key map [header-line mouse-2]
+ (lsp-headerline--make-mouse-handler
+ (dired-other-window full-path)))
+ map)
+ (format "mouse-1: browse '%s' with Dired\nmouse-2: browse '%s' with Dired in other window"
+ directory-display-string
+ directory-display-string)
+ (propertize directory-display-string
+ 'lsp-full-path full-path)))
+
+(declare-function evil-set-jump "ext:evil-jumps")
+
+(lsp-defun lsp-headerline--symbol-with-action ((symbol &as &DocumentSymbol :name) symbol-display-string)
+ "Build action for SYMBOL and SYMBOL-STRING."
+ (lsp-headerline--with-action (let ((map (make-sparse-keymap)))
+ (define-key map [header-line mouse-1]
+ (lsp-headerline--make-mouse-handler
+ (when (bound-and-true-p evil-mode)
+ (evil-set-jump))
+ (lsp-headerline--go-to-symbol symbol)))
+ (define-key map [header-line mouse-2]
+ (lsp-headerline--make-mouse-handler
+ (-let (((&DocumentSymbol :range (&RangeToPoint :start :end)) symbol))
+ (if (and (eq (point-min) start) (eq (point-max) end))
+ (widen)
+ (lsp-headerline--narrow-to-symbol symbol)))))
+ map)
+ (format "mouse-1: go to '%s' symbol\nmouse-2: %s"
+ name
+ (-let (((&DocumentSymbol :range (&RangeToPoint :start :end)) symbol))
+ (if (and (eq (point-min) start) (eq (point-max) end))
+ "widen"
+ (format "narrow to '%s' range" name))))
+ symbol-display-string))
+
+(defun lsp-headerline--path-up-to-project-root (root-path path)
+ "Find recursively the folders until the project ROOT-PATH.
+PATH is the current folder to be checked."
+ (let ((current-path path)
+ headerline-path-components)
+ (while (not (lsp-f-same? root-path current-path))
+ (push (lsp-headerline--directory-with-action current-path
+ (f-filename current-path))
+ headerline-path-components)
+ (setq current-path (lsp-f-parent current-path)))
+ headerline-path-components))
+
+(defun lsp-headerline--build-project-string ()
+ "Build the project-segment string for the breadcrumb."
+ (-if-let (root (lsp-workspace-root))
+ (propertize (lsp-headerline--directory-with-action
+ root
+ (f-filename root))
+ 'font-lock-face
+ 'lsp-headerline-breadcrumb-project-prefix-face)
+ (propertize "<unknown>"
+ 'font-lock-face
+ 'lsp-headerline-breadcrumb-unknown-project-prefix-face)))
+
+(defun lsp-headerline--build-file-string ()
+ "Build the file-segment string for the breadcrumb."
+ (let* ((file-path (buffer-file-name))
+ (filename (f-filename file-path)))
+ (if-let ((file-ext (f-ext file-path)))
+ (concat (lsp-icons-get-by-file-ext file-ext 'headerline-breadcrumb)
+ " "
+ (propertize filename
+ 'font-lock-face
+ (lsp-headerline--face-for-path file-path)))
+ filename)))
+
+
+(defun lsp-headerline--face-for-path (dir)
+ "Calculate the face for DIR."
+ (if-let ((diags (lsp-diagnostics-stats-for (directory-file-name dir))))
+ (cl-labels ((check-severity
+ (severity)
+ (not (zerop (aref diags severity)))))
+ (cond
+ ((not lsp-headerline-breadcrumb-enable-diagnostics)
+ 'lsp-headerline-breadcrumb-path-face)
+ ((check-severity lsp/diagnostic-severity-error)
+ 'lsp-headerline-breadcrumb-path-error-face)
+ ((check-severity lsp/diagnostic-severity-warning)
+ 'lsp-headerline-breadcrumb-path-warning-face)
+ ((check-severity lsp/diagnostic-severity-information)
+ 'lsp-headerline-breadcrumb-path-info-face)
+ ((check-severity lsp/diagnostic-severity-hint)
+ 'lsp-headerline-breadcrumb-path-hint-face)
+ (t 'lsp-headerline-breadcrumb-path-face)))
+ 'lsp-headerline-breadcrumb-path-face))
+
+(defun lsp-headerline--severity-level-for-range (range)
+ "Get the severiy level for RANGE."
+ (let ((range-severity 10))
+ (mapc (-lambda ((&Diagnostic :range (&Range :start) :severity?))
+ (when (lsp-point-in-range? start range)
+ (setq range-severity (min range-severity severity?))))
+ (lsp--get-buffer-diagnostics))
+ range-severity))
+
+(defun lsp-headerline--build-path-up-to-project-string ()
+ "Build the path-up-to-project segment for the breadcrumb."
+ (if-let ((root (lsp-workspace-root)))
+ (let ((segments (or
+ lsp-headerline--path-up-to-project-segments
+ (setq lsp-headerline--path-up-to-project-segments
+ (lsp-headerline--path-up-to-project-root
+ root
+ (lsp-f-parent (buffer-file-name)))))))
+ (mapconcat (lambda (next-dir)
+ (propertize next-dir
+ 'font-lock-face
+ (lsp-headerline--face-for-path
+ (get-text-property
+ 0 'lsp-full-path next-dir))))
+ segments
+ (concat " " (lsp-headerline--arrow-icon) " ")))
+ ""))
+
+(lsp-defun lsp-headerline--face-for-symbol ((&DocumentSymbol :deprecated?
+ :range))
+ "Get the face for SYMBOL."
+ (let ((range-severity (lsp-headerline--severity-level-for-range range)))
+ (cond
+ (deprecated? 'lsp-headerline-breadcrumb-deprecated-face)
+ ((not lsp-headerline-breadcrumb-enable-diagnostics)
+ 'lsp-headerline-breadcrumb-symbols-face)
+ ((= range-severity lsp/diagnostic-severity-error)
+ 'lsp-headerline-breadcrumb-symbols-error-face)
+ ((= range-severity lsp/diagnostic-severity-warning)
+ 'lsp-headerline-breadcrumb-symbols-warning-face)
+ ((= range-severity lsp/diagnostic-severity-information)
+ 'lsp-headerline-breadcrumb-symbols-info-face)
+ ((= range-severity lsp/diagnostic-severity-hint)
+ 'lsp-headerline-breadcrumb-symbols-hint-face)
+ (t 'lsp-headerline-breadcrumb-symbols-face))))
+
+(defun lsp-headerline--build-symbol-string ()
+ "Build the symbol segment for the breadcrumb."
+ (if (lsp-feature? "textDocument/documentSymbol")
+ (-if-let* ((lsp--document-symbols-request-async t)
+ (symbols (lsp--get-document-symbols))
+ (symbols-hierarchy (lsp--symbols->document-symbols-hierarchy symbols))
+ (enumerated-symbols-hierarchy
+ (-map-indexed (lambda (index elt)
+ (cons elt (1+ index)))
+ symbols-hierarchy)))
+ (mapconcat
+ (-lambda (((symbol &as &DocumentSymbol :name)
+ . index))
+ (let* ((symbol2-name
+ (propertize name
+ 'font-lock-face
+ (lsp-headerline--face-for-symbol symbol)))
+ (symbol2-icon (lsp-headerline--symbol-icon symbol))
+ (full-symbol-2
+ (concat
+ (if lsp-headerline-breadcrumb-enable-symbol-numbers
+ (concat
+ (propertize (number-to-string index)
+ 'face
+ 'lsp-headerline-breadcrumb-symbols-face)
+ " ")
+ "")
+ (if symbol2-icon
+ (concat symbol2-icon symbol2-name)
+ symbol2-name))))
+ (lsp-headerline--symbol-with-action symbol full-symbol-2)))
+ enumerated-symbols-hierarchy
+ (concat " " (lsp-headerline--arrow-icon) " "))
+ "")
+ ""))
+
+(defun lsp-headerline--build-string ()
+ "Build the header-line string."
+ (string-trim-right
+ (mapconcat
+ (lambda (segment)
+ (let ((segment-string
+ (pcase segment
+ ('project (lsp-headerline--build-project-string))
+ ('file (lsp-headerline--build-file-string))
+ ('path-up-to-project (lsp-headerline--build-path-up-to-project-string))
+ ('symbols (lsp-headerline--build-symbol-string))
+ (_ (lsp-log "'%s' is not a valid entry for `lsp-headerline-breadcrumb-segments'"
+ (symbol-name segment))
+ ""))))
+ (if (eq segment-string "")
+ ""
+ (concat (lsp-headerline--arrow-icon)
+ " "
+ segment-string
+ " "))))
+ lsp-headerline-breadcrumb-segments
+ "")))
+
+(defun lsp-headerline--check-breadcrumb (&rest _)
+ "Request for document symbols to build the breadcrumb."
+ (setq lsp-headerline--string (lsp-headerline--build-string))
+ (force-mode-line-update))
+
+(defun lsp-headerline--enable-breadcrumb ()
+ "Enable headerline breadcrumb mode."
+ (when (and lsp-headerline-breadcrumb-enable
+ (lsp-feature? "textDocument/documentSymbol"))
+ (lsp-headerline-breadcrumb-mode 1)))
+
+(defun lsp-headerline--disable-breadcrumb ()
+ "Disable headerline breadcrumb mode."
+ (lsp-headerline-breadcrumb-mode -1))
+
+;;;###autoload
+(define-minor-mode lsp-headerline-breadcrumb-mode
+ "Toggle breadcrumb on headerline."
+ :group 'lsp-headerline
+ :global nil
+ (cond
+ (lsp-headerline-breadcrumb-mode
+ (add-to-list 'header-line-format '(t (:eval lsp-headerline--string)))
+
+ (add-hook 'xref-after-jump-hook #'lsp-headerline--check-breadcrumb nil t)
+
+ (add-hook 'lsp-on-idle-hook #'lsp-headerline--check-breadcrumb nil t)
+ (add-hook 'lsp-configure-hook #'lsp-headerline--enable-breadcrumb nil t)
+ (add-hook 'lsp-unconfigure-hook #'lsp-headerline--disable-breadcrumb nil t))
+ (t
+ (remove-hook 'lsp-on-idle-hook #'lsp-headerline--check-breadcrumb t)
+ (remove-hook 'lsp-configure-hook #'lsp-headerline--enable-breadcrumb t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-headerline--disable-breadcrumb t)
+
+ (remove-hook 'xref-after-jump-hook #'lsp-headerline--check-breadcrumb t)
+
+ (setq lsp-headerline--path-up-to-project-segments nil)
+ (setq header-line-format (remove '(t (:eval lsp-headerline--string)) header-line-format)))))
+
+;;;###autoload
+(defun lsp-breadcrumb-go-to-symbol (symbol-position)
+ "Go to the symbol on breadcrumb at SYMBOL-POSITION."
+ (interactive "P")
+ (if (numberp symbol-position)
+ (if (lsp-feature? "textDocument/documentSymbol")
+ (-if-let* ((lsp--document-symbols-request-async t)
+ (symbols (lsp--get-document-symbols))
+ (symbols-hierarchy (lsp--symbols->document-symbols-hierarchy symbols)))
+ (lsp-headerline--go-to-symbol (nth (1- symbol-position) symbols-hierarchy))
+ (lsp--info "Symbol not found for position %s" symbol-position))
+ (lsp--info "Server does not support breadcrumb."))
+ (lsp--info "Call this function with a number representing the symbol position on breadcrumb")))
+
+(declare-function evil-set-command-property "ext:evil-common")
+
+(with-eval-after-load 'evil
+ (evil-set-command-property 'lsp-breadcrumb-go-to-symbol :jump t))
+
+;;;###autoload
+(defun lsp-breadcrumb-narrow-to-symbol (symbol-position)
+ "Narrow to the symbol range on breadcrumb at SYMBOL-POSITION."
+ (interactive "P")
+ (if (numberp symbol-position)
+ (if (lsp-feature? "textDocument/documentSymbol")
+ (-if-let* ((lsp--document-symbols-request-async t)
+ (symbols (lsp--get-document-symbols))
+ (symbols-hierarchy (lsp--symbols->document-symbols-hierarchy symbols)))
+ (lsp-headerline--narrow-to-symbol (nth (1- symbol-position) symbols-hierarchy))
+ (lsp--info "Symbol not found for position %s" symbol-position))
+ (lsp--info "Server does not support breadcrumb."))
+ (lsp--info "Call this function with a number representing the symbol position on breadcrumb")))
+
+(lsp-consistency-check lsp-headerline)
+
+(provide 'lsp-headerline)
+;;; lsp-headerline.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-html.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-html.el
new file mode 100644
index 0000000..0b44e16
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-html.el
@@ -0,0 +1,198 @@
+;;; lsp-html.el --- vscode-html-languageserver configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Vibhav Pant
+
+;; Author: Vibhav Pant <vibhavp@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-html nil
+ "LSP support for HTML, using vscode-html-languageserver."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/vscode-langservers/vscode-html-languageserver")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-experimental-custom-data nil
+ "A list of JSON file paths that define custom tags, properties and other HTML
+syntax constructs. Only workspace folder setting will be read."
+ :type '(choice (const nil) string)
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-enable t
+ "Enable/disable default HTML formatter."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-wrap-line-length 120
+ "Maximum amount of characters per line (0 = disable)."
+ :type 'number
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-unformatted "wbr"
+ nil
+ :type '(choice (const nil) string)
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-content-unformatted "pre,code,textarea"
+ nil
+ :group 'lsp-html
+ :type '(choice (const nil) string)
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-indent-inner-html nil
+ nil
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-preserve-new-lines t
+ "Controls whether existing line breaks before elements should be preserved.
+Only works before elements, not inside tags or for text."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-max-preserve-new-lines nil
+ nil
+ :type '(choice (const nil) integer)
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-indent-handlebars nil nil
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-end-with-newline nil
+ "End with a newline."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-extra-liners "head, body, /html"
+ nil
+ :type '(choice (const nil) string)
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-format-wrap-attributes "auto"
+ "Wrap attributes."
+ :type '(choice
+ (const "auto")
+ (const "force")
+ (const "force-aligned")
+ (const "force-expand-multiline")
+ (const "aligned-multiple")
+ (const "preserve")
+ (const "preserve-aligned"))
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-suggest-html5 t
+ "Controls whether the built-in HTML language support suggests HTML5 tags,
+properties and values."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-validate-scripts t
+ "Controls whether the built-in HTML language support validates embedded
+scripts."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-validate-styles t
+ "Controls whether the built-in HTML language support validates embedded
+styles."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-auto-closing-tags t
+ "Enable/disable autoclosing of HTML tags."
+ :type 'boolean
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-html-trace-server "off"
+ "Traces the communication between VS Code and the HTML language server."
+ :type '(choice
+ (const "off")
+ (const "messages")
+ (const "verbose"))
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-register-custom-settings
+ '(("html.trace.server" lsp-html-trace-server)
+ ("html.autoClosingTags" lsp-html-auto-closing-tags t)
+ ("html.validate.styles" lsp-html-validate-styles t)
+ ("html.validate.scripts" lsp-html-validate-scripts t)
+ ("html.suggest.html5" lsp-html-suggest-html5 t)
+ ("html.format.wrapAttributes" lsp-html-format-wrap-attributes)
+ ("html.format.extraLiners" lsp-html-format-extra-liners)
+ ("html.format.endWithNewline" lsp-html-format-end-with-newline t)
+ ("html.format.indentHandlebars" lsp-html-format-indent-handlebars t)
+ ("html.format.maxPreserveNewLines" lsp-html-format-max-preserve-new-lines)
+ ("html.format.preserveNewLines" lsp-html-format-preserve-new-lines t)
+ ("html.format.indentInnerHtml" lsp-html-format-indent-inner-html t)
+ ("html.format.contentUnformatted" lsp-html-format-content-unformatted)
+ ("html.format.unformatted" lsp-html-format-unformatted)
+ ("html.format.wrapLineLength" lsp-html-format-wrap-line-length)
+ ("html.format.enable" lsp-html-format-enable t)
+ ("html.experimental.customData" lsp-html-experimental-custom-data)))
+
+(defcustom lsp-html-server-command-args '("--stdio")
+ "Command to start html-languageserver."
+ :type '(repeat string)
+ :group 'lsp-html
+ :package-version '(lsp-mode . "6.3"))
+
+(lsp-dependency 'html-language-server
+ '(:system "html-languageserver")
+ '(:npm :package "vscode-html-languageserver-bin"
+ :path "html-languageserver"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ (cons (lsp-package-path 'html-language-server)
+ lsp-html-server-command-args)))
+ :activation-fn (lsp-activate-on "html")
+ :priority -4
+ :completion-in-comments? t
+ :server-id 'html-ls
+ :initialized-fn (lambda (w)
+ (with-lsp-workspace w
+ (lsp--set-configuration
+ (lsp-configuration-section "html"))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure
+ 'html-language-server callback
+ error-callback))))
+
+(lsp-consistency-check lsp-html)
+
+(provide 'lsp-html)
+;;; lsp-html.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-icons.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-icons.el
new file mode 100644
index 0000000..7bd8bc6
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-icons.el
@@ -0,0 +1,96 @@
+;;; lsp-icons.el --- LSP icons management -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP icons management
+;;
+;;; Code:
+(require 'lsp-mode)
+
+(defgroup lsp-icons nil
+ "LSP icons"
+ :group 'lsp-mode
+ :tag "LSP Icons")
+
+(defcustom lsp-headerline-breadcrumb-icons-enable t
+ "If non-nil, icons support is enabled for headerline-breadcrumb."
+ :type 'boolean
+ :group 'lsp-icons)
+
+(declare-function all-the-icons-material "ext:all-the-icons" t t)
+(declare-function lsp-treemacs-symbol-icon "ext:lsp-treemacs" (kind))
+(declare-function lsp-treemacs-get-icon "ext:lsp-treemacs" (icon-name))
+
+(defun lsp-icons--enabled-for-feature (feature)
+ "Check if icons support is enabled for FEATURE."
+ (cond
+ ((eq feature 'headerline-breadcrumb) lsp-headerline-breadcrumb-icons-enable)
+ (t t)))
+
+(defun lsp-icons--fix-image-background (image)
+ "Fix IMAGE background if it is a file otherwise return as an icon."
+ (if image
+ (let ((display-image (get-text-property 0 'display image)))
+ (if (and (listp display-image)
+ (plist-member (cl-copy-list (cl-rest display-image)) :type))
+ (propertize " " 'display
+ (cl-list* 'image
+ (plist-put
+ (cl-copy-list
+ (cl-rest display-image))
+ :background (face-attribute 'header-line :background nil t))))
+ (if (stringp display-image)
+ (replace-regexp-in-string "\s\\|\t" "" display-image)
+ (replace-regexp-in-string "\s\\|\t" "" image))))
+ ""))
+
+(defun lsp-icons-get-by-file-ext (file-ext &optional feature)
+ "Get an icon by file FILE-EXT.
+FEATURE is the feature that will use the icon which we should check
+if its enabled."
+ (when (and file-ext
+ (lsp-icons--enabled-for-feature feature)
+ (functionp 'lsp-treemacs-get-icon))
+ (lsp-icons--fix-image-background
+ (lsp-treemacs-get-icon file-ext))))
+
+(defun lsp-icons-get-by-symbol-kind (kind &optional feature)
+ "Get an icon by symbol KIND.
+FEATURE is the feature that will use the icon which we should check
+if its enabled."
+ (when (and kind
+ (lsp-icons--enabled-for-feature feature)
+ (functionp 'lsp-treemacs-symbol-icon))
+ (lsp-icons--fix-image-background
+ (lsp-treemacs-symbol-icon kind))))
+
+(defun lsp-icons-all-the-icons-material-icon (icon-name face fallback &optional feature)
+ "Get a material icon from all-the-icons by ICON-NAME using FACE.
+Fallback to FALLBACK string if not found or not available.
+FEATURE is the feature that will use the icon which we should check
+if its enabled."
+ (if (and (functionp 'all-the-icons-material)
+ (lsp-icons--enabled-for-feature feature))
+ (all-the-icons-material icon-name
+ :face face)
+ (propertize fallback 'face face)))
+
+(lsp-consistency-check lsp-icons)
+
+(provide 'lsp-icons)
+;;; lsp-icons.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ido.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ido.el
new file mode 100644
index 0000000..ac34dd7
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ido.el
@@ -0,0 +1,142 @@
+;;; lsp-ido.el --- `ido' integration -*- lexical-binding: t -*-
+;;
+;; Copyright (C) 2021 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This module provides an interactive ido interface to the workspace symbol
+;; functionality offered by lsp-mode.
+
+;;; Code:
+
+(require 'ido)
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defgroup lsp-ido nil
+ "LSP support for ido-based symbol completion"
+ :group 'lsp-mode
+ :tag "LSP ido")
+
+(defcustom lsp-ido-symbol-kind-to-string
+ [" " ; Unknown - 0
+ "File" ; File - 1
+ "Modu" ; Module - 2
+ "Nmsp" ; Namespace - 3
+ "Pack" ; Package - 4
+ "Clss" ; Class - 5
+ "Meth" ; Method - 6
+ "Prop" ; Property - 7
+ "Fld " ; Field - 8
+ "Cons" ; Constructor - 9
+ "Enum" ; Enum - 10
+ "Intf" ; Interface - 11
+ "Func" ; Function - 12
+ "Var " ; Variable - 13
+ "Cnst" ; Constant - 14
+ "Str " ; String - 15
+ "Num " ; Number - 16
+ "Bool " ; Boolean - 17
+ "Arr " ; Array - 18
+ "Obj " ; Object - 19
+ "Key " ; Key - 20
+ "Null" ; Null - 21
+ "EmMm" ; EnumMember - 22
+ "Srct" ; Struct - 23
+ "Evnt" ; Event - 24
+ "Op " ; Operator - 25
+ "TPar"] ; TypeParameter - 26
+ "A vector of 26 itens representing the SymbolKind."
+ :group 'lsp-ido
+ :type 'vector)
+
+(defcustom lsp-ido-show-symbol-filename
+ t
+ "Whether to show the project-relative path to a symbol's point of definition."
+ :group 'lsp-ido
+ :type 'boolean)
+
+(defcustom lsp-ido-show-symbol-kind
+ t
+ "Whether to show the symbol's kind when showing lsp symbols."
+ :group 'lsp-ido
+ :type 'boolean)
+
+(eval-when-compile
+ (lsp-interface
+ (lsp-ido:FormattedSymbolInformation
+ (:kind :name :location :textualRepresentation)
+ (:containerName :deprecated))))
+
+(lsp-defun lsp-ido--transform-candidate
+ ((symbol-information &as &SymbolInformation :kind :location (&Location :uri))
+ lsp-ido--results project-root)
+ (let* ((sanitized-kind (if (< kind (length lsp-ido-symbol-kind-to-string)) kind 0))
+ (type (elt lsp-ido-symbol-kind-to-string sanitized-kind))
+ (typestr (if lsp-ido-show-symbol-kind
+ (format "[%s] " type)
+ ""))
+ (pathstr (if lsp-ido-show-symbol-filename
+ (propertize (format " . %s" (file-relative-name (lsp--uri-to-path uri) project-root))
+ 'face 'font-lock-comment-face)
+ ""))
+ (textual-representation
+ (lsp-render-symbol-information symbol-information "."))
+ (entry (concat typestr textual-representation pathstr)))
+ (puthash entry symbol-information lsp-ido--results)))
+
+(lsp-defun lsp-ido--jump-selected-candidate
+ ((&SymbolInformation
+ :location (&Location :uri :range (&Range :start (&Position :line :character)))))
+ "Jump to selected candidate."
+ (find-file (lsp--uri-to-path uri))
+ (goto-char (point-min))
+ (forward-line line)
+ (forward-char character))
+
+(defun lsp-ido--workspace-symbol (workspaces query)
+ "Search against WORKSPACES based on QUERY."
+ (let* ((lsp-ido--results (make-hash-table :test 'equal))
+ (workspace-root (lsp-workspace-root))
+ (raw-choices
+ (with-lsp-workspaces workspaces
+ (lsp-request
+ "workspace/symbol"
+ (lsp-make-workspace-symbol-params :query query)))))
+ (mapc (lambda (it)
+ (lsp-ido--transform-candidate it lsp-ido--results workspace-root))
+ raw-choices)
+ lsp-ido--results))
+
+;;;###autoload
+(defun lsp-ido-workspace-symbol (arg)
+ "`ido' for lsp workspace/symbol.
+When called with prefix ARG the default selection will be symbol at point."
+ (interactive "P")
+ (let* ((query (if arg "" (read-string "Workspace symbol: ")))
+ (hash-table-candidates (lsp-ido--workspace-symbol (lsp-workspaces) query))
+ (choice (ido-completing-read
+ "Workspace symbol: "
+ (hash-table-keys hash-table-candidates)
+ nil
+ nil
+ (when arg (thing-at-point 'symbol)))))
+ (lsp-ido--jump-selected-candidate (gethash choice hash-table-candidates))))
+
+(lsp-consistency-check lsp-ido)
+
+(provide 'lsp-ido)
+;;; lsp-ido.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-iedit.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-iedit.el
new file mode 100644
index 0000000..ff1af0d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-iedit.el
@@ -0,0 +1,101 @@
+;;; lsp-iedit.el --- `iedit' integration -*- lexical-binding: t -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This module provides features that allow starting `iedit' on various
+;; different lsp-based, semantic units (like documentHighlights, and
+;; linkedEditingRanges in the future).
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'dash)
+
+(declare-function iedit-make-occurrence-overlay "iedit-lib" (begin end))
+(declare-function iedit-start-buffering "iedit-lib" ())
+(declare-function iedit-lib-start "iedit-lib" (mode-exit-func))
+(declare-function iedit-done "iedit" ())
+(declare-function evil-multiedit-state "evil-multiedit" ())
+
+(defvar iedit-mode)
+(defvar iedit-auto-buffering)
+(defvar iedit-occurrences-overlays)
+(defvar iedit-occurrence-keymap)
+(defvar iedit-mode-occurrence-keymap)
+(defvar evil-multiedit--dont-recall)
+
+(defun lsp-iedit--on-ranges (ranges)
+ "Start an `iedit' operation using RANGES.
+RANGES shall be a list of lsp-`&Range's. They can be acquired
+from various lsp protocol requests, e.g.
+`textDocument/documentHighlight', ...."
+ (require 'iedit)
+ (unless (seq-empty-p ranges)
+ (mapc (-lambda ((&RangeToPoint :start :end))
+ (push (iedit-make-occurrence-overlay start end)
+ iedit-occurrences-overlays))
+ ranges)
+ ;; See `iedit-start'; TODO: upstream this
+ (setq iedit-occurrence-keymap iedit-mode-occurrence-keymap)
+ (setq iedit-mode t)
+ (when iedit-auto-buffering
+ (iedit-start-buffering))
+ (iedit-lib-start 'iedit-done)
+ (run-hooks 'iedit-mode-hook)
+ (add-hook 'before-revert-hook 'iedit-done nil t)
+ (add-hook 'kbd-macro-termination-hook 'iedit-done nil t)
+ (add-hook 'change-major-mode-hook 'iedit-done nil t)
+ (add-hook 'iedit-aborting-hook 'iedit-done nil t)
+ (message "%d occurrences of \"%s\""
+ (seq-length ranges)
+ (lsp--range-text (lsp-seq-first ranges)))))
+
+;;;###autoload
+(defun lsp-iedit-highlights ()
+ "Start an `iedit' operation on the documentHighlights at point.
+This can be used as a primitive `lsp-rename' replacement if the
+language server doesn't support renaming.
+
+See also `lsp-enable-symbol-highlighting'."
+ (interactive)
+ (let ((highlights (lsp-request "textDocument/documentHighlight"
+ (lsp--text-document-position-params)))
+ (-compare-fn (-lambda ((&Location :range (&Range :start l-start :end l-end))
+ (&Location :range (&Range :start r-start :end r-end)))
+ (and (lsp--position-equal l-start r-start)
+ (lsp--position-equal l-end r-end)))))
+ (lsp-iedit--on-ranges (mapcar #'lsp:document-highlight-range (-distinct highlights)))))
+
+;;;###autoload
+(defun lsp-evil-multiedit-highlights ()
+ "Start an `evil-multiedit' operation on the documentHighlights at point.
+This can be used as a primitive `lsp-rename' replacement if the
+language server doesn't support renaming.
+
+See also `lsp-enable-symbol-highlighting'."
+ (interactive)
+ (require 'evil-multiedit)
+ (when (fboundp 'ahs-clear) (ahs-clear))
+ (setq evil-multiedit--dont-recall t)
+ (lsp-iedit-highlights)
+ (evil-multiedit-state))
+
+(lsp-consistency-check lsp-iedit)
+
+(provide 'lsp-iedit)
+;;; lsp-iedit.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-javascript.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-javascript.el
new file mode 100644
index 0000000..2f9e61f
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-javascript.el
@@ -0,0 +1,334 @@
+;;; lsp-javascript.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp,
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the JavaScript and TypeScript Programming Languages.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(lsp-dependency 'javascript-typescript-langserver
+ '(:system "javascript-typescript-stdio")
+ '(:npm :package "javascript-typescript-langserver"
+ :path "javascript-typescript-stdio"))
+
+(defgroup lsp-typescript-javascript nil
+ "Support for TypeScript/JavaScript, using Sourcegraph's JavaScript/TypeScript language server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/sourcegraph/javascript-typescript-langserver"))
+
+(defcustom lsp-clients-typescript-javascript-server-args '()
+ "Extra arguments for the typescript-language-server language server."
+ :group 'lsp-typescript-javascript
+ :risky t
+ :type '(repeat string))
+
+(defun lsp-typescript-javascript-tsx-jsx-activate-p (filename &optional _)
+ "Check if the javascript-typescript language server should be enabled based on FILENAME."
+ (or (string-match-p "\\.mjs\\|\\.[jt]sx?\\'" filename)
+ (and (derived-mode-p 'js-mode 'typescript-mode)
+ (not (derived-mode-p 'json-mode)))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda ()
+ (cons (lsp-package-path 'javascript-typescript-langserver)
+ lsp-clients-typescript-javascript-server-args)))
+ :activation-fn 'lsp-typescript-javascript-tsx-jsx-activate-p
+ :priority -3
+ :completion-in-comments? t
+ :server-id 'jsts-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure
+ 'javascript-typescript-langserver
+ callback
+ error-callback))))
+
+
+(defgroup lsp-typescript nil
+ "LSP support for TypeScript, using Theia/Typefox's TypeScript Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/theia-ide/typescript-language-server"))
+
+(defcustom lsp-clients-typescript-tls-path "typescript-language-server"
+ "Path to the typescript-language-server binary."
+ :group 'lsp-typescript
+ :risky t
+ :type 'string)
+
+(defcustom lsp-clients-typescript-server-args '("--stdio")
+ "Extra arguments for the typescript-language-server language server."
+ :group 'lsp-typescript
+ :risky t
+ :type '(repeat string))
+
+(defcustom lsp-clients-typescript-log-verbosity "info"
+ "The server log verbosity."
+ :group 'lsp-typescript
+ :type 'string)
+
+(defcustom lsp-clients-typescript-plugins (vector)
+ "The list of plugins to load.
+It should be a vector of plist with keys `:location' and `:name'
+where `:name' is the name of the package and `:location' is the
+directory containing the package. Example:
+\(vector
+ \(list :name \"@vsintellicode/typescript-intellicode-plugin\"
+ :location \"<path>.vscode/extensions/visualstudioexptteam.
+ vscodeintellicode-1.1.9/\"))"
+ :group 'lsp-typescript
+ :type '(restricted-sexp :tag "Vector"
+ :match-alternatives
+ (lambda (xs)
+ (and (vectorp xs) (seq-every-p
+ (-lambda ((&plist :name :location))
+ (and name location))
+ xs)))))
+
+(lsp-dependency 'typescript-language-server
+ '(:system lsp-clients-typescript-tls-path)
+ '(:npm :package "typescript-language-server"
+ :path "typescript-language-server"))
+
+(lsp-dependency 'typescript
+ '(:system "tsserver")
+ '(:npm :package "typescript"
+ :path "tsserver"))
+
+(defun lsp-javascript--rename (_workspace args)
+ (let ((path (lsp--uri-to-path (lsp-get (lsp-get args :textDocument) :uri))))
+ (if (f-exists? path)
+ (with-current-buffer (find-file path)
+ (goto-char (lsp--position-to-point
+ (lsp-get args :position))))
+ (error "There is no file %s" path)))
+ (call-interactively #'lsp-rename)
+ nil)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda ()
+ `(,(lsp-package-path 'typescript-language-server)
+ "--tsserver-path"
+ ,(lsp-package-path 'typescript)
+ ,@lsp-clients-typescript-server-args)))
+ :activation-fn 'lsp-typescript-javascript-tsx-jsx-activate-p
+ :priority -2
+ :completion-in-comments? t
+ :initialization-options (lambda ()
+ (list :plugins lsp-clients-typescript-plugins
+ :logVerbosity lsp-clients-typescript-log-verbosity
+ :tsServerPath (lsp-package-path 'typescript)))
+ :ignore-messages '("readFile .*? requested by TypeScript but content not available")
+ :server-id 'ts-ls
+ :request-handlers (ht ("_typescript.rename" #'lsp-javascript--rename))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure
+ 'typescript
+ (-partial #'lsp-package-ensure
+ 'typescript-language-server
+ callback
+ error-callback)
+ error-callback))))
+
+
+(defgroup lsp-flow nil
+ "LSP support for the Flow Javascript type checker."
+ :group 'lsp-mode
+ :link '(url-link "https://flow.org"))
+
+(defcustom lsp-clients-flow-server "flow"
+ "The Flow executable to use.
+Leave as just the executable name to use the default behavior of
+finding the executable with variable `exec-path'."
+ :group 'lsp-flow
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-flow-server-args '("lsp")
+ "Extra arguments for starting the Flow language server."
+ :group 'lsp-flow
+ :risky t
+ :type '(repeat string))
+
+(defun lsp-clients-flow-tag-file-present-p (file-name)
+ "Check if the '// @flow' or `/* @flow */' tag is present in
+the contents of FILE-NAME."
+ (if-let ((buffer (find-buffer-visiting file-name)))
+ (with-current-buffer buffer
+ (lsp-clients-flow-tag-string-present-p))
+ (with-temp-buffer
+ (insert-file-contents file-name)
+ (lsp-clients-flow-tag-string-present-p))))
+
+(defun lsp-clients-flow-tag-string-present-p ()
+ "Helper for `lsp-clients-flow-tag-file-present-p' that works
+with the file contents."
+ (save-excursion
+ (goto-char (point-min))
+ (let (stop found)
+ (while (not stop)
+ (unless (re-search-forward "[^\n[:space:]]" nil t)
+ (setq stop t))
+ (if (= (point) (point-min)) (setq stop t) (backward-char))
+ (cond ((or (looking-at "//+[ ]*@flow")
+ (looking-at "/\\**[ ]*@flow")
+ (looking-at "[ ]*\\*[ ]*@flow"))
+ (setq found t) (setq stop t))
+ ((or (looking-at "//") (looking-at "*"))
+ (forward-line))
+ ((looking-at "/\\*")
+ (save-excursion
+ (unless (re-search-forward "*/" nil t) (setq stop t)))
+ (forward-line))
+ (t (setq stop t))))
+ found)))
+
+(defun lsp-clients-flow-project-p (file-name)
+ "Check if FILE-NAME is part of a Flow project, that is, if
+there is a .flowconfig file in the folder hierarchy."
+ (locate-dominating-file file-name ".flowconfig"))
+
+(defun lsp-clients-flow-activate-p (file-name _mode)
+ "Check if the Flow language server should be enabled for a
+particular FILE-NAME and MODE."
+ (and (derived-mode-p 'js-mode 'web-mode 'js2-mode 'flow-js2-mode 'rjsx-mode)
+ (not (derived-mode-p 'json-mode))
+ (or (lsp-clients-flow-project-p file-name)
+ (lsp-clients-flow-tag-file-present-p file-name))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection
+ (lsp-stdio-connection (lambda ()
+ (cons lsp-clients-flow-server
+ lsp-clients-flow-server-args)))
+ :priority -1
+ :activation-fn 'lsp-clients-flow-activate-p
+ :server-id 'flow-ls))
+
+(defgroup lsp-deno nil
+ "LSP support for the Deno language server."
+ :group 'lsp-mode
+ :link '(url-link "https://deno.land/"))
+
+(defcustom lsp-clients-deno-server "deno"
+ "The Deno executable to use.
+Leave as just the executable name to use the default behavior of
+finding the executable with variable `exec-path'."
+ :group 'lsp-deno
+ :risky t
+ :type 'file
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-server-args '("lsp")
+ "Extra arguments for starting the Deno language server."
+ :group 'lsp-deno
+ :risky t
+ :type '(repeat string)
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-enable-lint t
+ "Controls if linting information will be provided by the Deno Language Server."
+ :group 'lsp-deno
+ :risky t
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-enable-code-lens-references t
+ "Enables or disables the display of code lens information."
+ :group 'lsp-deno
+ :risky t
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-enable-code-lens-references-all-functions t
+ "Enables or disables the display of code lens information for all functions.
+Setting this variable to `non-nil' implicitly enables
+`lsp-clients-deno-enable-code-lens-references'."
+ :group 'lsp-deno
+ :risky t
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-enable-code-lens-implementations t
+ "Enables or disables the display of code lens information for implementations."
+ :group 'lsp-deno
+ :risky t
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-config nil
+ "The file path to a tsconfig.json file.
+The path can be either be relative to the workspace, or an
+absolute path.
+
+Examples: `./tsconfig.json',
+`/path/to/tsconfig.json', `C:\\path\\to\\tsconfig.json'"
+ :group 'lsp-deno
+ :risky t
+ :type 'file
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-import-map nil
+ "The file path to an import map.
+Import maps provide a way to relocate modules based on their
+specifiers. The path can either be relative to the workspace, or
+an absolute path.
+
+Examples: `./import-map.json',
+`/path/to/import-map.json', `C:\\path\\to\\import-map.json'."
+ :group 'lsp-deno
+ :risky t
+ :type 'file
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-deno-enable-unstable nil
+ "Controls if code will be type checked with Deno's unstable APIs."
+ :group 'lsp-deno
+ :risky t
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defun lsp-clients-deno--make-init-options ()
+ "Initialization options for the Deno language server."
+ `(:enable t
+ :config ,lsp-clients-deno-config
+ :importMap ,lsp-clients-deno-import-map
+ :lint ,(lsp-json-bool lsp-clients-deno-enable-lint)
+ :unstable ,(lsp-json-bool lsp-clients-deno-enable-unstable)
+ :codeLens (:implementations ,(lsp-json-bool lsp-clients-deno-enable-code-lens-implementations)
+ :references ,(lsp-json-bool (or lsp-clients-deno-enable-code-lens-references
+ lsp-clients-deno-enable-code-lens-references-all-functions))
+ :referencesAllFunctions ,(lsp-json-bool lsp-clients-deno-enable-code-lens-references-all-functions))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection
+ (lsp-stdio-connection (lambda ()
+ (cons lsp-clients-deno-server
+ lsp-clients-deno-server-args)))
+ :initialization-options #'lsp-clients-deno--make-init-options
+ :priority -5
+ :activation-fn #'lsp-typescript-javascript-tsx-jsx-activate-p
+ :server-id 'deno-ls))
+
+(lsp-consistency-check lsp-javascript)
+
+(provide 'lsp-javascript)
+;;; lsp-javascript.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-json.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-json.el
new file mode 100644
index 0000000..127d5e4
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-json.el
@@ -0,0 +1,131 @@
+;;; lsp-json.el --- vscode-json-languageserver integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Kien Nguyen
+
+;; Author: kien.n.quang at gmail.com
+;; Keywords: lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'ht)
+(require 'url)
+(require 'url-util)
+
+(defgroup lsp-json nil
+ "LSP support for JSON, using vscode-json-languageserver."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/vscode-langservers/vscode-json-languageserver")
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-json-schemas nil
+ "Associate schemas to JSON files in the current project"
+ :type '(repeat alist)
+ :group 'lsp-json
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-http-proxy nil
+ "The URL of the proxy server to use when fetching schema."
+ :type 'string
+ :group 'lsp-json
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-http-proxyStrictSSL t
+ "The URL of the proxy server to use when fetching schema."
+ :type 'boolean
+ :group 'lsp-json
+ :package-version '(lsp-mode . "6.3"))
+
+(lsp-register-custom-settings
+ '(("json.schemas" lsp-json-schemas)
+ ("http.proxy" lsp-http-proxy)
+ ("http.proxyStrictSSL" lsp-http-proxyStrictSSL)))
+
+(defvar lsp-json--extra-init-params
+ `(:provideFormatter t
+ :handledSchemaProtocols ["file" "http" "https"]))
+
+(defvar lsp-json--schema-associations
+ `(:/*.css-data.json ["https://raw.githubusercontent.com/Microsoft/vscode-css-languageservice/master/docs/customData.schema.json"]
+ :/package.json ["http://json.schemastore.org/package"]
+ :/*.html-data.json ["https://raw.githubusercontent.com/Microsoft/vscode-html-languageservice/master/docs/customData.schema.json"]
+ :/*.schema.json ["http://json-schema.org/draft-07/schema#"]
+ :/bower.json ["http://json.schemastore.org/bower"]
+ :/composer.json ["http://json.schemastore.org/composer"]
+ :/tsconfig.json ["http://json.schemastore.org/tsconfig"]
+ :/tsconfig.*.json ["http://json.schemastore.org/tsconfig"]
+ :/typings.json ["http://json.schemastore.org/typings"]
+ :/.bowerrc ["http://json.schemastore.org/bowerrc"]
+ :/.babelrc ["http://json.schemastore.org/babelrc"]
+ :/.babelrc.json ["http://json.schemastore.org/babelrc"]
+ :/babel.config.json ["http://json.schemastore.org/babelrc"]
+ :/jsconfig.json ["http://json.schemastore.org/jsconfig"]
+ :/jsconfig.*.json ["http://json.schemastore.org/jsconfig"]
+ :/project.json ["http://json.schemastore.org/project"]
+ :/omnisharp.json ["http://json.schemastore.org/omnisharp"]
+ :/.eslintrc.json ["http://json.schemastore.org/eslintrc"]
+ :/.eslintrc ["http://json.schemastore.org/eslintrc"])
+ "Default json schemas.")
+
+(defun lsp-json--get-content (_workspace uri callback)
+ "Get content from URI."
+ (ignore-errors
+ (url-retrieve uri
+ (lambda (_status callback)
+ (goto-char (point-min))
+ (re-search-forward "\n\n" nil 'noerror)
+ (funcall
+ callback
+ (decode-coding-string (buffer-substring (point) (point-max))
+ 'utf-8-unix)))
+ (list callback))))
+
+(lsp-dependency 'vscode-json-languageserver
+ '(:system "vscode-json-languageserver")
+ '(:npm :package "vscode-json-languageserver"
+ :path "vscode-json-languageserver"))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection
+ (lsp-stdio-connection
+ (lambda () (list (lsp-package-path 'vscode-json-languageserver) "--stdio")))
+ :activation-fn (lsp-activate-on "json" "jsonc")
+ :server-id 'json-ls
+ :priority 0
+ :multi-root t
+ :completion-in-comments? t
+ :initialization-options lsp-json--extra-init-params
+ :async-request-handlers (ht ("vscode/content" #'lsp-json--get-content))
+ :initialized-fn
+ (lambda (w)
+ (with-lsp-workspace w
+ (lsp--set-configuration
+ (ht-merge (lsp-configuration-section "json")
+ (lsp-configuration-section "http")))
+ (lsp-notify "json/schemaAssociations" lsp-json--schema-associations)))
+ :download-server-fn
+ (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'vscode-json-languageserver callback error-callback))))
+
+(lsp-consistency-check lsp-json)
+
+(provide 'lsp-json)
+;;; lsp-json.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-kotlin.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-kotlin.el
new file mode 100644
index 0000000..329debc
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-kotlin.el
@@ -0,0 +1,121 @@
+;;; lsp-kotlin.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, kotlin
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Kotlin Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-kotlin nil
+ "LSP support for Kotlin, using KotlinLanguageServer."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/fwcd/KotlinLanguageServer"))
+
+(define-obsolete-variable-alias
+ 'lsp-kotlin-language-server-path
+ 'lsp-clients-kotlin-server-executable
+ "lsp-mode 6.4")
+
+(defcustom lsp-clients-kotlin-server-executable "kotlin-language-server"
+ "The kotlin-language-server executable to use.
+Leave as just the executable name to use the default behavior of finding the
+executable with `exec-path'."
+ :type 'string
+ :group 'lsp-kotlin)
+
+(defcustom lsp-kotlin-trace-server "off"
+ "Traces the communication between VSCode and the Kotlin language server."
+ :type '(choice (:tag "off" "messages" "verbose"))
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-compiler-jvm-target "1.8"
+ "Specifies the JVM target, e.g. \"1.6\" or \"1.8\"."
+ :type 'string
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-linting-debounce-time 250
+ "[DEBUG] Specifies the debounce time limit.
+Lower to increase responsiveness at the cost of possible stability issues."
+ :type 'number
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-completion-snippets-enabled t
+ "Specifies whether code completion should provide snippets (true) or
+plain-text items (false)."
+ :type 'boolean
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-debug-adapter-enabled t
+ "[Recommended] Specifies whether the debug adapter should be used.
+When enabled a debugger for Kotlin will be available."
+ :type 'boolean)
+
+(defcustom lsp-kotlin-debug-adapter-path ""
+ "Optionally a custom path to the debug adapter executable."
+ :type 'string
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-external-sources-use-kls-scheme t
+ "[Recommended] Specifies whether URIs inside JARs should be represented
+using the 'kls'-scheme."
+ :type 'boolean
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-kotlin-external-sources-auto-convert-to-kotlin t
+ "Specifies whether decompiled/external classes should be auto-converted
+to Kotlin."
+ :type 'boolean
+ :group 'lsp-kotlin
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-register-custom-settings
+ '(("kotlin.externalSources.autoConvertToKotlin" lsp-kotlin-external-sources-auto-convert-to-kotlin t)
+ ("kotlin.externalSources.useKlsScheme" lsp-kotlin-external-sources-use-kls-scheme t)
+ ("kotlin.debugAdapter.path" lsp-kotlin-debug-adapter-path)
+ ("kotlin.debugAdapter.enabled" lsp-kotlin-debug-adapter-enabled t)
+ ("kotlin.completion.snippets.enabled" lsp-kotlin-completion-snippets-enabled t)
+ ("kotlin.linting.debounceTime" lsp-kotlin-linting-debounce-time)
+ ("kotlin.compiler.jvm.target" lsp-kotlin-compiler-jvm-target)
+ ("kotlin.trace.server" lsp-kotlin-trace-server)
+ ("kotlin.languageServer.path" lsp-clients-kotlin-server-executable)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection lsp-clients-kotlin-server-executable)
+ :major-modes '(kotlin-mode)
+ :priority -1
+ :server-id 'kotlin-ls
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "kotlin"))))))
+
+(lsp-consistency-check lsp-kotlin)
+
+(provide 'lsp-kotlin)
+;;; lsp-kotlin.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lens.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lens.el
new file mode 100644
index 0000000..d08580a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lens.el
@@ -0,0 +1,425 @@
+;;; lsp-lens.el --- LSP lens -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP lens
+;;
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-lens nil
+ "LSP support for lens"
+ :prefix "lsp-lens-"
+ :group 'lsp-mode
+ :tag "LSP Lens")
+
+(defcustom lsp-lens-debounce-interval 0.001
+ "Debounce interval for loading lenses."
+ :group 'lsp-lens
+ :type 'number)
+
+(defcustom lsp-lens-place-position 'end-of-line
+ "The position to place lens relative to returned lens position."
+ :group 'lsp-lens
+ :type '(choice (const above-line)
+ (const end-of-line))
+ :package-version '(lsp-mode . "7.1"))
+
+(defface lsp-lens-mouse-face
+ '((t :height 0.8 :inherit link))
+ "The face used for code lens overlays."
+ :group 'lsp-lens)
+
+(defface lsp-lens-face
+ '((t :inherit lsp-details-face))
+ "The face used for code lens overlays."
+ :group 'lsp-lens)
+
+(defvar-local lsp-lens--modified? nil)
+
+(defvar-local lsp-lens--overlays nil
+ "Current lenses.")
+
+(defvar-local lsp-lens--page nil
+ "Pair of points which holds the last window location the lenses were loaded.")
+
+(defvar-local lsp-lens--last-count nil
+ "The number of lenses the last time they were rendered.")
+
+(defvar lsp-lens-backends '(lsp-lens--backend)
+ "Backends providing lenses.")
+
+(defvar-local lsp-lens--refresh-timer nil
+ "Refresh timer for the lenses.")
+
+(defvar-local lsp-lens--data nil
+ "Pair of points which holds the last window location the lenses were loaded.")
+
+(defvar-local lsp-lens--backend-cache nil)
+
+(defun lsp-lens--text-width (from to)
+ "Measure the width of the text between FROM and TO.
+Results are meaningful only if FROM and TO are on the same line."
+ ;; `current-column' takes prettification into account
+ (- (save-excursion (goto-char to) (current-column))
+ (save-excursion (goto-char from) (current-column))))
+
+(defun lsp-lens--update (ov)
+ "Redraw quick-peek overlay OV."
+ (let* ((offset (lsp-lens--text-width (save-excursion
+ (beginning-of-visual-line)
+ (point))
+ (save-excursion
+ (beginning-of-line-text)
+ (point))))
+ (str (if (eq 'end-of-line lsp-lens-place-position)
+ (overlay-get ov 'lsp--lens-contents)
+ (concat (make-string offset ?\s)
+ (overlay-get ov 'lsp--lens-contents)))))
+ (save-excursion
+ (goto-char (overlay-start ov))
+ (if (eq 'end-of-line lsp-lens-place-position)
+ (overlay-put ov 'after-string (propertize (concat " " str) 'cursor t))
+ (overlay-put ov 'before-string (concat str "\n")))
+ (overlay-put ov 'lsp-original str))))
+
+(defun lsp-lens--overlay-ensure-at (pos)
+ "Find or create a lens for the line at POS."
+ (-doto (save-excursion
+ (goto-char pos)
+ (if (eq 'end-of-line lsp-lens-place-position)
+ (make-overlay (point-at-eol) -1 nil t t)
+ (make-overlay (point-at-bol) (1+ (point-at-eol)) nil t t)))
+ (overlay-put 'lsp-lens t)
+ (overlay-put 'evaporate t)
+ (overlay-put 'lsp-lens-position pos)))
+
+(defun lsp-lens--show (str pos metadata)
+ "Show STR in an inline window at POS including METADATA."
+ (let ((ov (lsp-lens--overlay-ensure-at pos)))
+ (save-excursion
+ (goto-char pos)
+ (setf (overlay-get ov 'lsp--lens-contents) str)
+ (setf (overlay-get ov 'lsp--metadata) metadata)
+ (lsp-lens--update ov)
+ ov)))
+
+(defun lsp-lens--idle-function (&optional buffer)
+ "Create idle function for buffer BUFFER."
+ (when (and (or (not buffer) (eq (current-buffer) buffer))
+ (not (equal (cons (window-start) (window-end)) lsp-lens--page)))
+ (lsp-lens--schedule-refresh nil)))
+
+(defun lsp-lens--overlay-matches-pos (ov pos)
+ "Check if OV is a lens covering POS."
+ (and (overlay-get ov 'lsp-lens)
+ (overlay-start ov)
+ (<= (overlay-start ov) pos)
+ (< pos (overlay-end ov))))
+
+(defun lsp-lens--after-save ()
+ "Handler for `after-save-hook' for lens mode."
+ (lsp-lens--schedule-refresh t))
+
+(defun lsp-lens--schedule-refresh (&optional buffer-modified?)
+ "Call each of the backend.
+BUFFER-MODIFIED? determines whether the buffer was modified or
+not."
+ (-some-> lsp-lens--refresh-timer cancel-timer)
+
+ (setq lsp-lens--page (cons (window-start) (window-end)))
+ (setq lsp-lens--refresh-timer
+ (run-with-timer lsp-lens-debounce-interval
+ nil
+ #'lsp-lens-refresh
+ (or lsp-lens--modified? buffer-modified?)
+ (current-buffer))))
+
+(defun lsp-lens--schedule-refresh-modified ()
+ "Schedule a lens refresh due to a buffer-modification.
+See `lsp-lens--schedule-refresh' for details."
+ (lsp-lens--schedule-refresh t))
+
+(defun lsp-lens--keymap (command)
+ "Build the lens keymap for COMMAND."
+ (-doto (make-sparse-keymap)
+ (define-key [mouse-1] (lsp-lens--create-interactive-command command))))
+
+(defun lsp-lens--create-interactive-command (command?)
+ "Create an interactive COMMAND? for the lens.
+COMMAND? shall be an `&Command' (e.g. `&CodeLens' :command?) and
+mustn't be nil."
+ (if (functionp (lsp:command-command command?))
+ (lsp:command-command command?)
+ (lambda ()
+ (interactive)
+ (lsp--execute-command command?))))
+
+(defun lsp-lens--display (lenses)
+ "Show LENSES."
+ ;; rerender only if there are lenses which are not processed or if their count
+ ;; has changed(e. g. delete lens should trigger redisplay).
+ (let ((scroll-preserve-screen-position t))
+ (setq lsp-lens--modified? nil)
+ (when (or (-any? (-lambda ((&CodeLens :_processed processed))
+ (not processed))
+ lenses)
+ (eq (length lenses) lsp-lens--last-count)
+ (not lenses))
+ (setq lsp-lens--last-count (length lenses))
+ (mapc #'delete-overlay lsp-lens--overlays)
+ (setq lsp-lens--overlays
+ (->> lenses
+ (-filter #'lsp:code-lens-command?)
+ (--map (prog1 it (lsp-put it :_processed t)))
+ (-group-by (-compose #'lsp:position-line #'lsp:range-start #'lsp:code-lens-range))
+ (-map
+ (-lambda ((_ . lenses))
+ (let* ((sorted (-sort (-on #'< (-compose #'lsp:position-character
+ #'lsp:range-start
+ #'lsp:code-lens-range))
+ lenses))
+ (data (-map
+ (-lambda ((lens &as &CodeLens
+ :command? (command &as
+ &Command :title :_face face)))
+ (propertize
+ title
+ 'face (or face 'lsp-lens-face)
+ 'action (lsp-lens--create-interactive-command command)
+ 'pointer 'hand
+ 'mouse-face 'lsp-lens-mouse-face
+ 'local-map (lsp-lens--keymap command)))
+ sorted)))
+ (lsp-lens--show
+ (s-join (propertize "|" 'face 'lsp-lens-face) data)
+ (-> sorted cl-first lsp:code-lens-range lsp:range-start lsp--position-to-point)
+ data)))))))))
+
+(defun lsp-lens-refresh (buffer-modified? &optional buffer)
+ "Refresh lenses using lenses backend.
+BUFFER-MODIFIED? determines whether the BUFFER is modified or not."
+ (let ((buffer (or buffer (current-buffer))))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (dolist (backend lsp-lens-backends)
+ (funcall backend buffer-modified?
+ (lambda (lenses version)
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (lsp-lens--process backend lenses version))))))))))
+
+(defun lsp-lens--process (backend lenses version)
+ "Process LENSES originated from BACKEND.
+VERSION is the version of the file. The lenses has to be
+refreshed only when all backends have reported for the same
+version."
+ (setq lsp-lens--data (or lsp-lens--data (make-hash-table)))
+ (puthash backend (cons version (append lenses nil)) lsp-lens--data)
+
+ (-let [backend-data (->> lsp-lens--data ht-values (-filter #'cl-rest))]
+ (when (and
+ (= (length lsp-lens-backends) (ht-size lsp-lens--data))
+ (seq-every-p (-lambda ((version))
+ (or (not version) (eq version lsp--cur-version)))
+ backend-data))
+ ;; display the data only when the backends have reported data for the
+ ;; current version of the file
+ (lsp-lens--display (apply #'append (-map #'cl-rest backend-data)))))
+ version)
+
+(lsp-defun lsp--lens-backend-not-loaded? ((&CodeLens :range
+ (&Range :start)
+ :command?
+ :_pending pending))
+ "Return t if LENS has to be loaded."
+ (and (< (window-start) (lsp--position-to-point start) (window-end))
+ (not command?)
+ (not pending)))
+
+(lsp-defun lsp--lens-backend-present? ((&CodeLens :range (&Range :start) :command?))
+ "Return t if LENS has to be loaded."
+ (or command?
+ (not (< (window-start) (lsp--position-to-point start) (window-end)))))
+
+(defun lsp-lens--backend-fetch-missing (lenses callback file-version)
+ "Fetch LENSES without command in for the current window.
+
+TICK is the buffer modified tick. If it does not match
+`buffer-modified-tick' at the time of receiving the updates the
+updates must be discarded..
+CALLBACK - the callback for the lenses.
+FILE-VERSION - the version of the file."
+ (seq-each
+ (lambda (it)
+ (with-lsp-workspace (lsp-get it :_workspace)
+ (lsp-put it :_pending t)
+ (lsp-put it :_workspace nil)
+ (lsp-request-async "codeLens/resolve" it
+ (-lambda ((&CodeLens :command?))
+ (lsp-put it :_pending nil)
+ (lsp-put it :command command?)
+ (when (seq-every-p #'lsp--lens-backend-present? lenses)
+ (funcall callback lenses file-version)))
+ :mode 'tick)))
+ (seq-filter #'lsp--lens-backend-not-loaded? lenses)))
+
+(defun lsp-lens--backend (modified? callback)
+ "Lenses backend using `textDocument/codeLens'.
+MODIFIED? - t when buffer is modified since the last invocation.
+CALLBACK - callback for the lenses."
+ (when (lsp--find-workspaces-for "textDocument/codeLens")
+ (if modified?
+ (progn
+ (setq lsp-lens--backend-cache nil)
+ (lsp-request-async "textDocument/codeLens"
+ `(:textDocument (:uri ,(lsp--buffer-uri)))
+ (lambda (lenses)
+ (setq lsp-lens--backend-cache
+ (seq-mapcat
+ (-lambda ((workspace . workspace-lenses))
+ ;; preserve the original workspace so we can later use it to resolve the lens
+ (seq-do (-rpartial #'lsp-put :_workspace workspace) workspace-lenses)
+ workspace-lenses)
+ lenses))
+ (if (-every? #'lsp:code-lens-command? lsp-lens--backend-cache)
+ (funcall callback lsp-lens--backend-cache lsp--cur-version)
+ (lsp-lens--backend-fetch-missing lsp-lens--backend-cache callback lsp--cur-version)))
+ :error-handler #'ignore
+ :mode 'tick
+ :no-merge t
+ :cancel-token (concat (buffer-name (current-buffer)) "-lenses")))
+ (if (-all? #'lsp--lens-backend-present? lsp-lens--backend-cache)
+ (funcall callback lsp-lens--backend-cache lsp--cur-version)
+ (lsp-lens--backend-fetch-missing lsp-lens--backend-cache callback lsp--cur-version)))))
+
+;;;###autoload
+(defun lsp-lens--enable ()
+ "Enable lens mode."
+ (when (and lsp-lens-enable
+ (lsp-feature? "textDocument/codeLens"))
+ (lsp-lens-mode 1)))
+
+(defun lsp-lens--disable ()
+ "Disable lens mode."
+ (lsp-lens-mode -1))
+
+;;;###autoload
+(defun lsp-lens-show ()
+ "Display lenses in the buffer."
+ (interactive)
+ (->> (lsp-request "textDocument/codeLens"
+ `(:textDocument (:uri
+ ,(lsp--path-to-uri buffer-file-name))))
+ (seq-map (-lambda ((lens &as &CodeAction :command?))
+ (if command?
+ lens
+ (lsp-request "codeLens/resolve" lens))))
+ lsp-lens--display))
+
+;;;###autoload
+(defun lsp-lens-hide ()
+ "Delete all lenses."
+ (interactive)
+ (let ((scroll-preserve-screen-position t))
+ (seq-do #'delete-overlay lsp-lens--overlays)
+ (setq lsp-lens--overlays nil)))
+
+;;;###autoload
+(define-minor-mode lsp-lens-mode
+ "Toggle code-lens overlays."
+ :group 'lsp-lens
+ :global nil
+ :init-value nil
+ :lighter " Lens"
+ (cond
+ (lsp-lens-mode
+ (add-hook 'lsp-unconfigure-hook #'lsp-lens--disable nil t)
+ (add-hook 'lsp-configure-hook #'lsp-lens--enable nil t)
+ (add-hook 'lsp-on-idle-hook #'lsp-lens--idle-function nil t)
+ (add-hook 'lsp-on-change-hook #'lsp-lens--schedule-refresh-modified nil t)
+ (add-hook 'after-save-hook #'lsp-lens--after-save nil t)
+ (add-hook 'before-revert-hook #'lsp-lens-hide nil t)
+ (lsp-lens-refresh t))
+ (t
+ (remove-hook 'lsp-on-idle-hook #'lsp-lens--idle-function t)
+ (remove-hook 'lsp-on-change-hook #'lsp-lens--schedule-refresh-modified t)
+ (remove-hook 'after-save-hook #'lsp-lens--after-save t)
+ (remove-hook 'before-revert-hook #'lsp-lens-hide t)
+ (when lsp-lens--refresh-timer
+ (cancel-timer lsp-lens--refresh-timer))
+ (setq lsp-lens--refresh-timer nil)
+ (lsp-lens-hide)
+ (setq lsp-lens--last-count nil)
+ (setq lsp-lens--backend-cache nil)
+ (remove-hook 'lsp-configure-hook #'lsp-lens--enable t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-lens--disable t))))
+
+
+;; avy integration
+
+(declare-function avy-process "ext:avy" (candidates &optional overlay-fn cleanup-fn))
+(declare-function avy--key-to-char "ext:avy" (c))
+(defvar avy-action)
+
+;;;###autoload
+(defun lsp-avy-lens ()
+ "Click lsp lens using `avy' package."
+ (interactive)
+ (unless lsp-lens--overlays
+ (user-error "No lenses in current buffer"))
+ (let* ((avy-action 'identity)
+ (action (cl-third
+ (avy-process
+ (-mapcat
+ (lambda (overlay)
+ (-map-indexed
+ (lambda (index lens-token)
+ (list overlay index
+ (get-text-property 0 'action lens-token)))
+ (overlay-get overlay 'lsp--metadata)))
+ lsp-lens--overlays)
+ (-lambda (path ((ov index) . _win))
+ (let* ((path (mapcar #'avy--key-to-char path))
+ (str (propertize (string (car (last path)))
+ 'face 'avy-lead-face))
+ (old-str (overlay-get ov 'before-string))
+ (old-str-tokens (s-split "|" old-str))
+ (old-token (seq-elt old-str-tokens index))
+ (tokens `(,@(-take index old-str-tokens)
+ ,(-if-let ((_ prefix suffix)
+ (s-match "\\(^[[:space:]]+\\)\\(.*\\)" old-token))
+ (concat prefix str suffix)
+ (concat str old-token))
+ ,@(-drop (1+ index) old-str-tokens)))
+ (new-str (s-join (propertize "|" 'face 'lsp-lens-face) tokens))
+ (new-str (if (s-ends-with? "\n" new-str)
+ new-str
+ (concat new-str "\n"))))
+ (overlay-put ov 'before-string new-str)))
+ (lambda ()
+ (--map (overlay-put it 'before-string
+ (overlay-get it 'lsp-original))
+ lsp-lens--overlays))))))
+ (when action (funcall-interactively action))))
+
+(lsp-consistency-check lsp-lens)
+
+(provide 'lsp-lens)
+;;; lsp-lens.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lua.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lua.el
new file mode 100644
index 0000000..2e76745
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-lua.el
@@ -0,0 +1,678 @@
+;;; lsp-lua.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 E. Alexander Barbosa
+
+;; Author: E. Alexander Barbosa <elxbarbosa@outlook.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Lua Programming Language
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'f)
+(require 'files)
+
+(defgroup lsp-emmy-lua nil
+ "Lua LSP client, provided by the EmmyLua Language Server."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/EmmyLua/EmmyLua-LanguageServer"))
+
+(defcustom lsp-clients-emmy-lua-java-path "java"
+ "Java Runtime binary location."
+ :group 'lsp-emmy-lua
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-emmy-lua-jar-path (f-join lsp-server-install-dir "EmmyLua-LS-all.jar")
+ "Emmy Lua language server jar file."
+ :group 'lsp-emmy-lua
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-emmy-lua-args '("-jar")
+ "Arguments to the Lua Language server."
+ :group 'lsp-emmy-lua
+ :version "7.1"
+ :risky t
+ :type '(repeat string))
+
+(defcustom lsp-clients-emmy-lua-command nil
+ "Final command to call the Lua Language server."
+ :group 'lsp-emmy-lua
+ :version "7.1"
+ :risky t
+ :type '(repeat string))
+
+(defun lsp-clients-emmy-lua-test ()
+ "Test the Emmy Lua binaries and files."
+ (and (executable-find lsp-clients-emmy-lua-java-path)
+ (f-exists? lsp-clients-emmy-lua-jar-path)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () (or lsp-clients-emmy-lua-command
+ `(,lsp-clients-emmy-lua-java-path
+ ,@lsp-clients-emmy-lua-args
+ ,lsp-clients-emmy-lua-jar-path)))
+ #'lsp-clients-emmy-lua-test)
+ :major-modes '(lua-mode)
+ :server-id 'emmy-lua
+ :priority -1
+ :notification-handlers (lsp-ht ("emmy/progressReport" #'ignore))))
+
+
+;;; lua-language-server
+(defgroup lsp-lua-language-server nil
+ "Lua LSP client, provided by the Lua Language Server."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/sumneko/lua-language-server"))
+
+(defcustom lsp-clients-lua-language-server-install-dir (f-join lsp-server-install-dir "lua-language-server/")
+ "Installation directory for Lua Language Server."
+ :group 'lsp-lua-language-server
+ :version "7.1"
+ :risky t
+ :type 'directory)
+
+(defcustom lsp-clients-lua-language-server-bin
+ (f-join lsp-clients-lua-language-server-install-dir
+ "extension/server/bin/"
+ (pcase system-type
+ ('gnu/linux "Linux/lua-language-server")
+ ('darwin "macOS/lua-language-server")
+ ('windows-nt "Windows/lua-language-server.exe")
+ (_ "Linux/lua-language-server")))
+ "Location of Lua Language Server."
+ :group 'lsp-lua-language-server
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-lua-language-server-main-location
+ (f-join lsp-clients-lua-language-server-install-dir
+ "extension/server/main.lua")
+ "Location of Lua Language Server main.lua."
+ :group 'lsp-lua-language-server
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-lua-language-server-args '("-E")
+ "Arguments to run the Lua Language server."
+ :group 'lsp-lua-language-server
+ :version "7.1"
+ :risky t
+ :type '(repeat string))
+
+(defcustom lsp-clients-lua-language-server-command nil
+ "Command to start Lua Language server."
+ :group 'lsp-lua-language-server
+ :type '(repeat string))
+
+
+(defun lsp-clients-lua-language-server-test ()
+ "Test Lua language server binaries and files."
+ (and (f-exists? lsp-clients-lua-language-server-main-location)
+ (f-exists? lsp-clients-lua-language-server-bin)))
+
+(defcustom lsp-lua-color-mode "Semantic"
+ "Color mode."
+ :type '(choice (:tag "Grammar" "Semantic"))
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-completion-call-snippet "Disable"
+ "Shows function call snippets."
+ :type '(choice (:tag "Disable" "Both" "Replace"))
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-completion-display-context 6
+ "Previewing the relevant code snippet of the suggestion may help you
+understand the usage of the suggestion.
+
+The number set indicates the number of intercepted lines in the code
+fragment. If it is set to `0`, this feature can be disabled."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-completion-enable t
+ "Enable completion."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-completion-keyword-snippet "Replace"
+ "Shows keyword syntax snippets."
+ :type '(choice (:tag "Disable" "Both" "Replace"))
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-completion-workspace-word t
+ "Show words within the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-develop-debugger-port 11412
+ "Listen port of debugger."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-develop-debugger-wait nil
+ "Suspend before debugger connects."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-develop-enable nil
+ "Developer mode. Do not enable, performance will be affected."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-disable nil
+ "Disabled diagnostic (Use code in hover brackets).
+```json
+\"Lua.diagnostics.disable\" : [
+\"unused-local\",
+\"lowercase-global\"
+]
+```"
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-enable t
+ "Enable diagnostics."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-globals nil
+ "Defined global variables.
+```json
+\"Lua.diagnostics.globals\" : [
+\"GLOBAL1\",
+\"GLOBAL2\"
+]
+```"
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-needed-file-status nil
+ "If you want to check only opened files, choice Opened; else choice Any.
+```json
+\"Lua.diagnostics.neededFileStatus\" : {
+\"ambiguity-1\" : \"Any\",
+\"circle-doc-class\" : \"Opened\"
+}
+```"
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-severity nil
+ "Modified diagnostic severity.
+```json
+\"Lua.diagnostics.severity\" : {
+\"redefined-local\" : \"Warning\",
+\"emmy-lua\" : \"Hint\"
+}
+```"
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-workspace-delay 0
+ "Latency (milliseconds) for workspace diagnostics. When you start the
+workspace, or edit any file, the entire workspace will be re-diagnosed in the
+background. Set to negative to disable workspace diagnostics."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-diagnostics-workspace-rate 100
+ "Workspace diagnostics run rate (%). Decreasing this value reduces CPU usage,
+but also reduces the speed of workspace diagnostics. The diagnosis of the file
+you are currently editing is always done at full speed and is not affected by
+this setting."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hint-enable nil
+ "Enable hint."
+ :type 'boolean
+ :package-version '(lsp-mmode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hint-param-name t
+ "Hint parameter name when the parameter called is literal."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hint-param-type t
+ "Show type hints at the parameter of the function."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hint-set-type nil
+ "Hint type at assignment operation."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-enable t
+ "Enable hover."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-field-infer 3000
+ "When hovering to view a table, type infer will be performed for each field.
+When the accumulated time of type infer reaches the set value (MS), the type
+infer of subsequent fields will be skipped."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-preview-fields 100
+ "When hovering to view a table, limits the maximum number of previews for
+fields."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-view-number t
+ "Hover to view numeric content (only if literal is not decimal)."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-view-string t
+ "Hover to view the contents of a string (only if the literal contains an
+escape character)."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-hover-view-string-max 1000
+ "The maximum length of a hover to view the contents of a string."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-intelli-sense-search-depth 0
+ "Set the search depth for IntelliSense. Increasing this value increases
+accuracy, but decreases performance. Different workspace have different
+tolerance for this setting. Please adjust it to the appropriate value."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-file-encoding "utf8"
+ "File encoding. The 'ansi' option is only available under the 'Windows'
+platform."
+ :type '(choice (:tag "utf8" "ansi"))
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-nonstandard-symbol nil
+ "Supports non-standard symbols. Make sure that your runtime environment
+supports these symbols."
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-path
+ ["?.lua" "?/init.lua" "?/?.lua"]
+ "`package.path`."
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-plugin nil
+ "(Proposed) Plugin path. Default is `.vscode/lua/plugin.lua`"
+ :type 'file
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-special nil
+ "The custom global variables are regarded as some special built-in variables,
+and the language server will provide special support.
+```json
+\"Lua.runtime.special\" : {
+\"include\" : \"require\"
+}
+```"
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-unicode-name nil
+ "Allows Unicode characters in name."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-runtime-version "Lua 5.4"
+ "Lua runtime version."
+ :type '(choice (:tag "Lua 5.1" "Lua 5.2" "Lua 5.3" "Lua 5.4" "LuaJIT"))
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-signature-help-enable t
+ "Enable signature help."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-telemetry-enable nil
+ "Enable telemetry to send your editor information and error logs over the
+network."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-window-progress-bar t
+ "Show progress bar in status bar."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-window-status-bar t
+ "Show extension status in status bar."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-ignore-dir
+ [".vscode"]
+ "Ignored directories (Use `.gitignore` grammar).
+```json
+\"Lua.workspace.ignoreDir\" : [
+\"temp/*.*\",
+\"!temp/*.lua\"
+]
+```"
+ :type 'lsp-string-vector
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-ignore-submodules t
+ "Ignore submodules."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-library nil
+ "Load external library.
+
+This feature can load external Lua files, which can be used for definition,
+automatic completion and other functions. Note that the language server does
+not monitor changes in external files and needs to restart if the external
+files are modified. The following example shows loaded files in `C:/lua`
+and `../lib` ,exclude `../lib/temp`.
+
+```json
+\"Lua.workspace.library\": {
+\"C:/lua\": true,
+\"../lib\": [
+\"temp/*\"
+]
+}
+```"
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-max-preload 1000
+ "Max preloaded files."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-preload-file-size 100
+ "Skip files larger than this value (KB) when preloading."
+ :type 'number
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-workspace-use-git-ignore t
+ "Ignore files list in `.gitignore` ."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-files-associations nil
+ "Files.associations."
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(defcustom lsp-lua-files-exclude nil
+ "Files.exclude."
+ :type 'alist
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-lua-language-server)
+
+(lsp-register-custom-settings
+ '(("files.associations" lsp-lua-files-associations t)
+ ("files.exclude" lsp-lua-files-exclude t)
+ ("Lua.workspace.useGitIgnore" lsp-lua-workspace-use-git-ignore t)
+ ("Lua.workspace.preloadFileSize" lsp-lua-workspace-preload-file-size)
+ ("Lua.workspace.maxPreload" lsp-lua-workspace-max-preload)
+ ("Lua.workspace.library" lsp-lua-workspace-library)
+ ("Lua.workspace.ignoreSubmodules" lsp-lua-workspace-ignore-submodules t)
+ ("Lua.workspace.ignoreDir" lsp-lua-workspace-ignore-dir)
+ ("Lua.window.statusBar" lsp-lua-window-status-bar t)
+ ("Lua.window.progressBar" lsp-lua-window-progress-bar t)
+ ("Lua.telemetry.enable" lsp-lua-telemetry-enable t)
+ ("Lua.signatureHelp.enable" lsp-lua-signature-help-enable t)
+ ("Lua.runtime.version" lsp-lua-runtime-version)
+ ("Lua.runtime.unicodeName" lsp-lua-runtime-unicode-name nil)
+ ("Lua.runtime.special" lsp-lua-runtime-special)
+ ("Lua.runtime.plugin" lsp-lua-runtime-plugin)
+ ("Lua.runtime.path" lsp-lua-runtime-path)
+ ("Lua.runtime.nonstandardSymbol" lsp-lua-runtime-nonstandard-symbol)
+ ("Lua.runtime.fileEncoding" lsp-lua-runtime-file-encoding)
+ ("Lua.intelliSense.searchDepth" lsp-lua-intelli-sense-search-depth)
+ ("Lua.hover.viewStringMax" lsp-lua-hover-view-string-max)
+ ("Lua.hover.viewString" lsp-lua-hover-view-string t)
+ ("Lua.hover.viewNumber" lsp-lua-hover-view-number t)
+ ("Lua.hover.previewFields" lsp-lua-hover-preview-fields)
+ ("Lua.hover.fieldInfer" lsp-lua-hover-field-infer)
+ ("Lua.hover.enable" lsp-lua-hover-enable t)
+ ("Lua.hint.setType" lsp-lua-hint-set-type nil)
+ ("Lua.hint.paramType" lsp-lua-hint-param-type t)
+ ("Lua.hint.paramName" lsp-lua-hint-param-name t)
+ ("Lua.hint.enable" lsp-lua-hint-enable t)
+ ("Lua.diagnostics.workspaceRate" lsp-lua-diagnostics-workspace-rate)
+ ("Lua.diagnostics.workspaceDelay" lsp-lua-diagnostics-workspace-delay)
+ ("Lua.diagnostics.severity" lsp-lua-diagnostics-severity)
+ ("Lua.diagnostics.neededFileStatus" lsp-lua-diagnostics-needed-file-status)
+ ("Lua.diagnostics.globals" lsp-lua-diagnostics-globals)
+ ("Lua.diagnostics.enable" lsp-lua-diagnostics-enable t)
+ ("Lua.diagnostics.disable" lsp-lua-diagnostics-disable)
+ ("Lua.develop.enable" lsp-lua-develop-enable t)
+ ("Lua.develop.debuggerWait" lsp-lua-develop-debugger-wait t)
+ ("Lua.develop.debuggerPort" lsp-lua-develop-debugger-port)
+ ("Lua.completion.workspaceWord" lsp-lua-completion-workspace-word t)
+ ("Lua.completion.keywordSnippet" lsp-lua-completion-keyword-snippet)
+ ("Lua.completion.enable" lsp-lua-completion-enable t)
+ ("Lua.completion.displayContext" lsp-lua-completion-display-context)
+ ("Lua.completion.callSnippet" lsp-lua-completion-call-snippet)
+ ("Lua.color.mode" lsp-lua-color-mode)))
+
+(defun lsp-lua-language-server-install (client callback error-callback update?)
+ "Download the latest version of lua-language-server and extract it to
+`lsp-lua-language-server-install-dir'."
+ (ignore client update?)
+ (let ((store-path (expand-file-name "vs-lua" lsp-clients-lua-language-server-install-dir)))
+ (lsp-download-install
+ (lambda (&rest _)
+ (set-file-modes lsp-clients-lua-language-server-bin #o0700)
+ (funcall callback))
+ error-callback
+ :url (lsp-vscode-extension-url "sumneko" "lua" "1.17.4")
+ :store-path store-path
+ :decompress :zip)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () (or lsp-clients-lua-language-server-command
+ `(,lsp-clients-lua-language-server-bin
+ ,@lsp-clients-lua-language-server-args
+ ,lsp-clients-lua-language-server-main-location)))
+ #'lsp-clients-lua-language-server-test)
+ :major-modes '(lua-mode)
+ :priority -2
+ :server-id 'lua-language-server
+ :download-server-fn #'lsp-lua-language-server-install))
+
+
+;;; lua-lsp
+(defgroup lsp-lua-lsp nil
+ "Lua LSP client, provided by the Lua-Lsp."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/Alloyed/lua-lsp"))
+
+(defcustom lsp-clients-luarocks-bin-dir (f-join (getenv "HOME") ".luarocks/bin/")
+ "LuaRocks bin directory."
+ :group 'lsp-lua-lsp
+ :version "7.1"
+ :risky t
+ :type 'directory)
+
+(defcustom lsp-clients-lua-lsp-server-install-dir nil
+ "Installation directory for Lua-Lsp Language Server."
+ :group 'lsp-lua-lsp
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defun lsp-clients-lua-lsp-test ()
+ "Test Lua-lsp language server files."
+ (and (f-exists? lsp-clients-lua-lsp-server-install-dir)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda ()
+ (or lsp-clients-lua-lsp-server-install-dir
+ (f-join lsp-clients-luarocks-bin-dir "lua-lsp")))
+ #'lsp-clients-lua-lsp-test)
+ :major-modes '(lua-mode)
+ :priority -3
+ :server-id 'lsp-lua-lsp))
+
+;;; lua-roblox-language-server
+(defgroup lsp-lua-roblox-language-server nil
+ "Roblox Lua LSP client, provided by the Roblox Lua Language Server."
+ :group 'lsp-mode
+ :version "7.1"
+ :link '(url-link "https://github.com/NightrainsRbx/RobloxLsp"))
+
+(defcustom lsp-lua-roblox-language-server-install-dir (f-join lsp-server-install-dir "lua-roblox-language-server/")
+ "Installation directory for Lua Language Server."
+ :group 'lsp-lua-roblox-language-server
+ :version "7.1"
+ :risky t
+ :type 'directory)
+
+(defcustom lsp-lua-roblox-language-server-bin
+ (f-join lsp-lua-roblox-language-server-install-dir
+ "extension/server/bin/"
+ (pcase system-type
+ ('gnu/linux "Linux/lua-language-server")
+ ('darwin "macOS/lua-language-server")
+ ('windows-nt "Windows/lua-language-server.exe")
+ (_ "Linux/lua-language-server")))
+ "Location of Roblox Lua Language Server."
+ :group 'lsp-lua-roblox-language-server
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-lua-roblox-language-server-main-location
+ (f-join lsp-lua-roblox-language-server-install-dir
+ "extension/server/main.lua")
+ "Location of Roblox Lua Language Server main.lua."
+ :group 'lsp-lua-roblox-language-server
+ :version "7.1"
+ :risky t
+ :type 'file)
+
+(defcustom lsp-lua-roblox-server-download-url
+ (lsp-vscode-extension-url "Nightrains" "robloxlsp" "0.15.8")
+ "Download url for Roblox Lua vscode extension."
+ :group 'lsp-lua-roblox-language-server
+ :version "7.1"
+ :type 'string)
+
+(defcustom lsp-lua-roblox-server-store-path
+ (expand-file-name "vs-lua-roblox" lsp-lua-roblox-language-server-install-dir)
+ "Server file name for the vscode extension."
+ :group 'lsp-lua-roblox-language-server
+ :version "7.1"
+ :type 'string)
+
+(defun lsp-lua-roblox-language-server-test ()
+ "Test Lua language server binaries and files."
+ (and (f-exists? lsp-lua-roblox-language-server-main-location)
+ (f-exists? lsp-lua-roblox-language-server-bin)))
+
+(defun lsp-lua-roblox-language-server-install (_client callback error-callback _update?)
+ "Download the latest version of lua-language-server and extract it to
+`lsp-lua-roblox-language-server-download-url'."
+ (lsp-download-install
+ (lambda (&rest _)
+ (set-file-modes lsp-lua-roblox-language-server-bin #o0700)
+ (funcall callback))
+ error-callback
+ :url lsp-lua-roblox-server-download-url
+ :store-path lsp-lua-roblox-server-store-path
+ :decompress :zip))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () (or lsp-clients-lua-language-server-command
+ `(,lsp-lua-roblox-language-server-bin
+ ,@lsp-clients-lua-language-server-args
+ ,lsp-lua-roblox-language-server-main-location)))
+ #'lsp-lua-roblox-language-server-test)
+ :major-modes '(lua-mode)
+ :priority -4
+ :server-id 'lua-roblox-language-server
+ :download-server-fn #'lsp-lua-roblox-language-server-install))
+
+(lsp-consistency-check lsp-lua)
+
+(provide 'lsp-lua)
+;;; lsp-lua.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-markdown.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-markdown.el
new file mode 100644
index 0000000..ae01dfa
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-markdown.el
@@ -0,0 +1,105 @@
+;;; lsp-markdown.el --- lsp-mode markdown integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 lsp-mode maintainers
+
+;; Author: lsp-mode maintainers
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for unified-language-server
+
+;;; Code:
+
+(require 'lsp-mode)
+
+;;; Markdown
+(defgroup lsp-markdown nil
+ "Settings for the markdown language server client."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/unifiedjs/unified-language-server")
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-markdown-server-command "unified-language-server"
+ "The binary (or full path to binary) which executes the server."
+ :type 'string
+ :group 'lsp-markdown
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-markdown-server-command-args '("--parser=remark-parse" "--stdio")
+ "Command-line arguments for the markdown lsp server."
+ :type '(repeat 'string)
+ :group 'lsp-markdown
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-markdown-remark-plugins [["#remark-preset-lint-markdown-style-guide"]]
+ "The JSON configuration object for plugins.
+
+For a complete list of plugins, check:
+ https://github.com/unifiedjs/unified-language-server/blob/main/CONFIGURATION.md#re-using-settings"
+ :type 'lsp-string-vector
+ :group 'lsp-markdown
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-markdown-remark-check-text-with-setting "retext-english"
+ "Configure `checkTextWith' subproperty.
+
+For a complete list of plugins, check:
+ https://github.com/unifiedjs/unified-language-server/blob/main/CONFIGURATION.md#re-using-settings"
+ :type '(choice (
+ (const "retext-english")
+ (const "remark-parse")))
+ :group 'lsp-markdown
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-markdown-remark-check-text-with-mutator ["#remark-retext" "#parse-latin"]
+ "Vector of additional mutators.
+
+For a complete list of plugins, check:
+ https://github.com/unifiedjs/unified-language-server/blob/main/CONFIGURATION.md#re-using-settings"
+ :type 'lsp-string-vector
+ :group 'lsp-markdown
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-dependency 'unified-language-server
+ '(:system "unified-language-server")
+ '(:npm :package "unified-language-server"
+ :path "unified-language-server"))
+
+(lsp-register-custom-settings
+ `(("unified-language-server.remark-parse.plugins" lsp-markdown-remark-plugins)
+ ("unified-language-server.remark-parse.checkTextWith.setting" lsp-markdown-remark-check-text-with-setting)
+ ("unified-language-server.remark-parse.checkTextWith.mutator" lsp-markdown-remark-check-text-with-mutator)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ (cons (or (executable-find lsp-markdown-server-command)
+ (lsp-package-path 'unified-language-server))
+ lsp-markdown-server-command-args)))
+ :activation-fn (lsp-activate-on "markdown")
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "unified-language-server"))))
+ :major-modes '(markdown-mode)
+ :priority -1
+ :major-modes '(markdown-mode)
+ :server-id 'unified))
+
+(lsp-consistency-check lsp-markdown)
+
+(provide 'lsp-markdown)
+;;; lsp-markdown.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-autoloads.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-autoloads.el
new file mode 100644
index 0000000..6f040a4
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-autoloads.el
@@ -0,0 +1,745 @@
+;;; lsp-mode-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "lsp-actionscript" "lsp-actionscript.el" (0
+;;;;;; 0 0 0))
+;;; Generated autoloads from lsp-actionscript.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-actionscript" '("lsp-actionscript-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ada" "lsp-ada.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ada.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ada" '("lsp-ada-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-angular" "lsp-angular.el" (0 0 0 0))
+;;; Generated autoloads from lsp-angular.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-angular" '("lsp-client")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-bash" "lsp-bash.el" (0 0 0 0))
+;;; Generated autoloads from lsp-bash.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-bash" '("lsp-bash-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-beancount" "lsp-beancount.el" (0 0 0 0))
+;;; Generated autoloads from lsp-beancount.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-beancount" '("lsp-beancount-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-clangd" "lsp-clangd.el" (0 0 0 0))
+;;; Generated autoloads from lsp-clangd.el
+
+(autoload 'lsp-cpp-flycheck-clang-tidy-error-explainer "lsp-clangd" "\
+Explain a clang-tidy ERROR by scraping documentation from llvm.org.
+
+\(fn ERROR)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-clangd" '("lsp-c")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-clojure" "lsp-clojure.el" (0 0 0 0))
+;;; Generated autoloads from lsp-clojure.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-clojure" '("lsp-clojure-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-completion" "lsp-completion.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-completion.el
+
+(define-obsolete-variable-alias 'lsp-prefer-capf 'lsp-completion-provider "lsp-mode 7.0.1")
+
+(define-obsolete-variable-alias 'lsp-enable-completion-at-point 'lsp-completion-enable "lsp-mode 7.0.1")
+
+(autoload 'lsp-completion-at-point "lsp-completion" "\
+Get lsp completions." nil nil)
+
+(autoload 'lsp-completion--enable "lsp-completion" "\
+Enable LSP completion support." nil nil)
+
+(autoload 'lsp-completion-mode "lsp-completion" "\
+Toggle LSP completion support.
+
+If called interactively, enable Lsp-Completion mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(add-hook 'lsp-configure-hook (lambda nil (when (and lsp-auto-configure lsp-completion-enable) (lsp-completion--enable))))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-completion" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-crystal" "lsp-crystal.el" (0 0 0 0))
+;;; Generated autoloads from lsp-crystal.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-crystal" '("lsp-clients-crystal-executable")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-csharp" "lsp-csharp.el" (0 0 0 0))
+;;; Generated autoloads from lsp-csharp.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-csharp" '("lsp-csharp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-css" "lsp-css.el" (0 0 0 0))
+;;; Generated autoloads from lsp-css.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-css" '("lsp-css-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-diagnostics" "lsp-diagnostics.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from lsp-diagnostics.el
+
+(define-obsolete-variable-alias 'lsp-diagnostic-package 'lsp-diagnostics-provider "lsp-mode 7.0.1")
+
+(define-obsolete-variable-alias 'lsp-flycheck-default-level 'lsp-diagnostics-flycheck-default-level "lsp-mode 7.0.1")
+
+(autoload 'lsp-diagnostics-lsp-checker-if-needed "lsp-diagnostics" nil nil nil)
+
+(autoload 'lsp-diagnostics--enable "lsp-diagnostics" "\
+Enable LSP checker support." nil nil)
+
+(autoload 'lsp-diagnostics-mode "lsp-diagnostics" "\
+Toggle LSP diagnostics integration.
+
+If called interactively, enable Lsp-Diagnostics mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(add-hook 'lsp-configure-hook (lambda nil (when lsp-auto-configure (lsp-diagnostics--enable))))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-diagnostics" '("lsp-diagnostics-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-dired" "lsp-dired.el" (0 0 0 0))
+;;; Generated autoloads from lsp-dired.el
+
+(defvar lsp-dired-mode nil "\
+Non-nil if Lsp-Dired mode is enabled.
+See the `lsp-dired-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `lsp-dired-mode'.")
+
+(custom-autoload 'lsp-dired-mode "lsp-dired" nil)
+
+(autoload 'lsp-dired-mode "lsp-dired" "\
+Display `lsp-mode' icons for each file in a dired buffer.
+
+If called interactively, enable Lsp-Dired mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-dired" '("lsp-dired-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-dockerfile" "lsp-dockerfile.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-dockerfile.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-dockerfile" '("lsp-dockerfile-language-server-command")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-elixir" "lsp-elixir.el" (0 0 0 0))
+;;; Generated autoloads from lsp-elixir.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-elixir" '("lsp-elixir-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-elm" "lsp-elm.el" (0 0 0 0))
+;;; Generated autoloads from lsp-elm.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-elm" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-erlang" "lsp-erlang.el" (0 0 0 0))
+;;; Generated autoloads from lsp-erlang.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-erlang" '("lsp-erlang-server-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-eslint" "lsp-eslint.el" (0 0 0 0))
+;;; Generated autoloads from lsp-eslint.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-eslint" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-fortran" "lsp-fortran.el" (0 0 0 0))
+;;; Generated autoloads from lsp-fortran.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-fortran" '("lsp-clients-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-fsharp" "lsp-fsharp.el" (0 0 0 0))
+;;; Generated autoloads from lsp-fsharp.el
+
+(autoload 'lsp-fsharp--workspace-load "lsp-fsharp" "\
+Load all of the provided PROJECTS.
+
+\(fn PROJECTS)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-fsharp" '("lsp-fsharp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-gdscript" "lsp-gdscript.el" (0 0 0 0))
+;;; Generated autoloads from lsp-gdscript.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-gdscript" '("lsp-gdscript-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-go" "lsp-go.el" (0 0 0 0))
+;;; Generated autoloads from lsp-go.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-go" '("lsp-go-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-groovy" "lsp-groovy.el" (0 0 0 0))
+;;; Generated autoloads from lsp-groovy.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-groovy" '("lsp-groovy-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-hack" "lsp-hack.el" (0 0 0 0))
+;;; Generated autoloads from lsp-hack.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-hack" '("lsp-clients-hack-command")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-haxe" "lsp-haxe.el" (0 0 0 0))
+;;; Generated autoloads from lsp-haxe.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-haxe" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-headerline" "lsp-headerline.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-headerline.el
+
+(autoload 'lsp-headerline-breadcrumb-mode "lsp-headerline" "\
+Toggle breadcrumb on headerline.
+
+If called interactively, enable Lsp-Headerline-Breadcrumb mode if
+ARG is positive, and disable it if ARG is zero or negative. If
+called from Lisp, also enable the mode if ARG is omitted or nil,
+and toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'lsp-breadcrumb-go-to-symbol "lsp-headerline" "\
+Go to the symbol on breadcrumb at SYMBOL-POSITION.
+
+\(fn SYMBOL-POSITION)" t nil)
+
+(autoload 'lsp-breadcrumb-narrow-to-symbol "lsp-headerline" "\
+Narrow to the symbol range on breadcrumb at SYMBOL-POSITION.
+
+\(fn SYMBOL-POSITION)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-headerline" '("lsp-headerline-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-html" "lsp-html.el" (0 0 0 0))
+;;; Generated autoloads from lsp-html.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-html" '("lsp-html-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-icons" "lsp-icons.el" (0 0 0 0))
+;;; Generated autoloads from lsp-icons.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-icons" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ido" "lsp-ido.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ido.el
+
+(autoload 'lsp-ido-workspace-symbol "lsp-ido" "\
+`ido' for lsp workspace/symbol.
+When called with prefix ARG the default selection will be symbol at point.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ido" '("lsp-ido-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-iedit" "lsp-iedit.el" (0 0 0 0))
+;;; Generated autoloads from lsp-iedit.el
+
+(autoload 'lsp-iedit-highlights "lsp-iedit" "\
+Start an `iedit' operation on the documentHighlights at point.
+This can be used as a primitive `lsp-rename' replacement if the
+language server doesn't support renaming.
+
+See also `lsp-enable-symbol-highlighting'." t nil)
+
+(autoload 'lsp-evil-multiedit-highlights "lsp-iedit" "\
+Start an `evil-multiedit' operation on the documentHighlights at point.
+This can be used as a primitive `lsp-rename' replacement if the
+language server doesn't support renaming.
+
+See also `lsp-enable-symbol-highlighting'." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-iedit" '("lsp-iedit--on-ranges")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-javascript" "lsp-javascript.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-javascript.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-javascript" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-json" "lsp-json.el" (0 0 0 0))
+;;; Generated autoloads from lsp-json.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-json" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-kotlin" "lsp-kotlin.el" (0 0 0 0))
+;;; Generated autoloads from lsp-kotlin.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-kotlin" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-lens" "lsp-lens.el" (0 0 0 0))
+;;; Generated autoloads from lsp-lens.el
+
+(autoload 'lsp-lens--enable "lsp-lens" "\
+Enable lens mode." nil nil)
+
+(autoload 'lsp-lens-show "lsp-lens" "\
+Display lenses in the buffer." t nil)
+
+(autoload 'lsp-lens-hide "lsp-lens" "\
+Delete all lenses." t nil)
+
+(autoload 'lsp-lens-mode "lsp-lens" "\
+Toggle code-lens overlays.
+
+If called interactively, enable Lsp-Lens mode if ARG is positive,
+and disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it if
+ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'lsp-avy-lens "lsp-lens" "\
+Click lsp lens using `avy' package." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-lens" '("lsp-lens-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-lua" "lsp-lua.el" (0 0 0 0))
+;;; Generated autoloads from lsp-lua.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-lua" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-markdown" "lsp-markdown.el" (0 0 0 0))
+;;; Generated autoloads from lsp-markdown.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-markdown" '("lsp-markdown-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-mode" "lsp-mode.el" (0 0 0 0))
+;;; Generated autoloads from lsp-mode.el
+(put 'lsp-enable-file-watchers 'safe-local-variable #'booleanp)
+(put 'lsp-file-watch-threshold 'safe-local-variable (lambda (i) (or (numberp i) (not i))))
+
+(autoload 'lsp-load-vscode-workspace "lsp-mode" "\
+Load vscode workspace from FILE
+
+\(fn FILE)" t nil)
+
+(autoload 'lsp-save-vscode-workspace "lsp-mode" "\
+Save vscode workspace to FILE
+
+\(fn FILE)" t nil)
+
+(autoload 'lsp-install-server "lsp-mode" "\
+Interactively install server.
+When prefix UPDATE? is t force installation even if the server is present.
+
+\(fn UPDATE\\=\\? &optional SERVER-ID)" t nil)
+
+(autoload 'lsp-ensure-server "lsp-mode" "\
+Ensure server SERVER-ID
+
+\(fn SERVER-ID)" nil nil)
+
+(autoload 'lsp "lsp-mode" "\
+Entry point for the server startup.
+When ARG is t the lsp mode will start new language server even if
+there is language server which can handle current language. When
+ARG is nil current file will be opened in multi folder language
+server if there is such. When `lsp' is called with prefix
+argument ask the user to select which language server to start.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'lsp-deferred "lsp-mode" "\
+Entry point that defers server startup until buffer is visible.
+`lsp-deferred' will wait until the buffer is visible before invoking `lsp'.
+This avoids overloading the server with many files when starting Emacs." nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-mode" '("lsp-" "make-lsp-client" "when-lsp-workspace" "with-lsp-workspace")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-modeline" "lsp-modeline.el" (0 0 0 0))
+;;; Generated autoloads from lsp-modeline.el
+
+(define-obsolete-variable-alias 'lsp-diagnostics-modeline-scope 'lsp-modeline-diagnostics-scope "lsp-mode 7.0.1")
+
+(autoload 'lsp-modeline-code-actions-mode "lsp-modeline" "\
+Toggle code actions on modeline.
+
+If called interactively, enable Lsp-Modeline-Code-Actions mode if
+ARG is positive, and disable it if ARG is zero or negative. If
+called from Lisp, also enable the mode if ARG is omitted or nil,
+and toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(define-obsolete-function-alias 'lsp-diagnostics-modeline-mode 'lsp-modeline-diagnostics-mode "lsp-mode 7.0.1")
+
+(autoload 'lsp-modeline-diagnostics-mode "lsp-modeline" "\
+Toggle diagnostics modeline.
+
+If called interactively, enable Lsp-Modeline-Diagnostics mode if
+ARG is positive, and disable it if ARG is zero or negative. If
+called from Lisp, also enable the mode if ARG is omitted or nil,
+and toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'lsp-modeline-workspace-status-mode "lsp-modeline" "\
+Toggle workspace status on modeline.
+
+If called interactively, enable Lsp-Modeline-Workspace-Status
+mode if ARG is positive, and disable it if ARG is zero or
+negative. If called from Lisp, also enable the mode if ARG is
+omitted or nil, and toggle it if ARG is `toggle'; disable the
+mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-modeline" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-nix" "lsp-nix.el" (0 0 0 0))
+;;; Generated autoloads from lsp-nix.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-nix" '("lsp-nix-server-path")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ocaml" "lsp-ocaml.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ocaml.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ocaml" '("lsp-ocaml-l")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-perl" "lsp-perl.el" (0 0 0 0))
+;;; Generated autoloads from lsp-perl.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-perl" '("lsp-perl-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-php" "lsp-php.el" (0 0 0 0))
+;;; Generated autoloads from lsp-php.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-php" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-prolog" "lsp-prolog.el" (0 0 0 0))
+;;; Generated autoloads from lsp-prolog.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-prolog" '("lsp-prolog-server-command")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-protocol" "lsp-protocol.el" (0 0 0 0))
+;;; Generated autoloads from lsp-protocol.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-protocol" '("dash-expand:&RangeToPoint" "lsp")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-purescript" "lsp-purescript.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-purescript.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-purescript" '("lsp-purescript-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-pwsh" "lsp-pwsh.el" (0 0 0 0))
+;;; Generated autoloads from lsp-pwsh.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-pwsh" '("lsp-pwsh-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-pyls" "lsp-pyls.el" (0 0 0 0))
+;;; Generated autoloads from lsp-pyls.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-pyls" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-pylsp" "lsp-pylsp.el" (0 0 0 0))
+;;; Generated autoloads from lsp-pylsp.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-pylsp" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-r" "lsp-r.el" (0 0 0 0))
+;;; Generated autoloads from lsp-r.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-r" '("lsp-clients-r-server-command")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-racket" "lsp-racket.el" (0 0 0 0))
+;;; Generated autoloads from lsp-racket.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-racket" '("lsp-racket-lang")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-rf" "lsp-rf.el" (0 0 0 0))
+;;; Generated autoloads from lsp-rf.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-rf" '("expand-start-command" "lsp-rf-language-server-" "parse-rf-language-server-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-rust" "lsp-rust.el" (0 0 0 0))
+;;; Generated autoloads from lsp-rust.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-rust" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-semantic-tokens" "lsp-semantic-tokens.el"
+;;;;;; (0 0 0 0))
+;;; Generated autoloads from lsp-semantic-tokens.el
+
+(autoload 'lsp--semantic-tokens-initialize-buffer "lsp-semantic-tokens" "\
+Initialize the buffer for semantic tokens.
+IS-RANGE-PROVIDER is non-nil when server supports range requests." nil nil)
+
+(autoload 'lsp--semantic-tokens-initialize-workspace "lsp-semantic-tokens" "\
+Initialize semantic tokens for WORKSPACE.
+
+\(fn WORKSPACE)" nil nil)
+
+(autoload 'lsp-semantic-tokens--warn-about-deprecated-setting "lsp-semantic-tokens" "\
+Warn about deprecated semantic highlighting variable." nil nil)
+
+(autoload 'lsp-semantic-tokens--enable "lsp-semantic-tokens" "\
+Enable semantic tokens mode." nil nil)
+
+(autoload 'lsp-semantic-tokens-mode "lsp-semantic-tokens" "\
+Toggle semantic-tokens support.
+
+If called interactively, enable Lsp-Semantic-Tokens mode if ARG
+is positive, and disable it if ARG is zero or negative. If
+called from Lisp, also enable the mode if ARG is omitted or nil,
+and toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-semantic-tokens" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-solargraph" "lsp-solargraph.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from lsp-solargraph.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-solargraph" '("lsp-solargraph-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-sorbet" "lsp-sorbet.el" (0 0 0 0))
+;;; Generated autoloads from lsp-sorbet.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-sorbet" '("lsp-sorbet-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-sqls" "lsp-sqls.el" (0 0 0 0))
+;;; Generated autoloads from lsp-sqls.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-sqls" '("lsp-sql")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-steep" "lsp-steep.el" (0 0 0 0))
+;;; Generated autoloads from lsp-steep.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-steep" '("lsp-steep-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-svelte" "lsp-svelte.el" (0 0 0 0))
+;;; Generated autoloads from lsp-svelte.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-svelte" '("lsp-svelte-plugin-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-terraform" "lsp-terraform.el" (0 0 0 0))
+;;; Generated autoloads from lsp-terraform.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-terraform" '("lsp-terraform-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-tex" "lsp-tex.el" (0 0 0 0))
+;;; Generated autoloads from lsp-tex.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-tex" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-v" "lsp-v.el" (0 0 0 0))
+;;; Generated autoloads from lsp-v.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-v" '("lsp-v-vls-executable")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-vala" "lsp-vala.el" (0 0 0 0))
+;;; Generated autoloads from lsp-vala.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-vala" '("lsp-clients-vala-ls-executable")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-verilog" "lsp-verilog.el" (0 0 0 0))
+;;; Generated autoloads from lsp-verilog.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-verilog" '("lsp-clients-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-vetur" "lsp-vetur.el" (0 0 0 0))
+;;; Generated autoloads from lsp-vetur.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-vetur" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-vhdl" "lsp-vhdl.el" (0 0 0 0))
+;;; Generated autoloads from lsp-vhdl.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-vhdl" '("ghdl-ls-bin-name" "hdl-checker-bin-name" "lsp-vhdl-" "vhdl-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-vimscript" "lsp-vimscript.el" (0 0 0 0))
+;;; Generated autoloads from lsp-vimscript.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-vimscript" '("lsp-clients-vim-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-xml" "lsp-xml.el" (0 0 0 0))
+;;; Generated autoloads from lsp-xml.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-xml" '("lsp-xml-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-yaml" "lsp-yaml.el" (0 0 0 0))
+;;; Generated autoloads from lsp-yaml.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-yaml" '("lsp-yaml-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-zig" "lsp-zig.el" (0 0 0 0))
+;;; Generated autoloads from lsp-zig.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-zig" '("lsp-zig-zls-executable")))
+
+;;;***
+
+;;;### (autoloads nil nil ("lsp-cmake.el" "lsp-d.el" "lsp-dhall.el"
+;;;;;; "lsp-mode-pkg.el" "lsp-nim.el" "lsp.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; lsp-mode-autoloads.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-pkg.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-pkg.el
new file mode 100644
index 0000000..3093b63
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode-pkg.el
@@ -0,0 +1,18 @@
+(define-package "lsp-mode" "20210716.2233" "LSP mode"
+ '((emacs "26.1")
+ (dash "2.18.0")
+ (f "0.20.0")
+ (ht "2.3")
+ (spinner "1.7.3")
+ (markdown-mode "2.3")
+ (lv "0"))
+ :commit "21dd93ee4add2086d9006e0e6143553bdaa61519" :authors
+ '(("Vibhav Pant, Fangrui Song, Ivan Yonchovski"))
+ :maintainer
+ '("Vibhav Pant, Fangrui Song, Ivan Yonchovski")
+ :keywords
+ '("languages")
+ :url "https://github.com/emacs-lsp/lsp-mode")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode.el
new file mode 100644
index 0000000..0fd635b
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-mode.el
@@ -0,0 +1,8656 @@
+;;; lsp-mode.el --- LSP mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: Vibhav Pant, Fangrui Song, Ivan Yonchovski
+;; Keywords: languages
+;; Package-Requires: ((emacs "26.1") (dash "2.18.0") (f "0.20.0") (ht "2.3") (spinner "1.7.3") (markdown-mode "2.3") (lv "0"))
+;; Version: 7.1.0
+
+;; URL: https://github.com/emacs-lsp/lsp-mode
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Emacs client/library for the Language Server Protocol
+
+;;; Code:
+
+(require 'cl-generic)
+(require 'cl-lib)
+(require 'compile)
+(require 'dash)
+(require 'epg)
+(require 'ewoc)
+(require 'f)
+(require 'filenotify)
+(require 'files)
+(require 'ht)
+(require 'imenu)
+(require 'inline)
+(require 'json)
+(require 'lv)
+(require 'markdown-mode)
+(require 'network-stream)
+(require 'pcase)
+(require 'rx)
+(require 's)
+(require 'seq)
+(require 'spinner)
+(require 'subr-x)
+(require 'tree-widget)
+(require 'url-parse)
+(require 'url-util)
+(require 'widget)
+(require 'xref)
+(require 'minibuffer)
+(require 'yasnippet nil t)
+(require 'lsp-protocol)
+
+(defgroup lsp-mode nil
+ "Language Server Protocol client."
+ :group 'tools
+ :tag "Language Server (lsp-mode)")
+
+(declare-function evil-set-command-property "ext:evil-common")
+(declare-function projectile-project-root "ext:projectile")
+(declare-function yas-expand-snippet "ext:yasnippet")
+(declare-function dap-mode "ext:dap-mode")
+(declare-function dap-auto-configure-mode "ext:dap-mode")
+
+(defvar yas-inhibit-overlay-modification-protection)
+(defvar yas-indent-line)
+(defvar yas-wrap-around-region)
+(defvar yas-also-auto-indent-first-line)
+(defvar dap-auto-configure-mode)
+(defvar dap-ui-menu-items)
+(defvar company-minimum-prefix-length)
+
+(defconst lsp--message-type-face
+ `((1 . ,compilation-error-face)
+ (2 . ,compilation-warning-face)
+ (3 . ,compilation-message-face)
+ (4 . ,compilation-info-face)))
+
+(defconst lsp--errors
+ '((-32700 "Parse Error")
+ (-32600 "Invalid Request")
+ (-32601 "Method not Found")
+ (-32602 "Invalid Parameters")
+ (-32603 "Internal Error")
+ (-32099 "Server Start Error")
+ (-32000 "Server End Error")
+ (-32002 "Server Not Initialized")
+ (-32001 "Unknown Error Code")
+ (-32800 "Request Cancelled"))
+ "Alist of error codes to user friendly strings.")
+
+(defconst lsp--empty-ht (make-hash-table))
+
+(eval-and-compile
+ (defun dash-expand:&lsp-wks (key source)
+ `(,(intern-soft (format "lsp--workspace-%s" (eval key))) ,source))
+
+ (defun dash-expand:&lsp-cln (key source)
+ `(,(intern-soft (format "lsp--client-%s" (eval key))) ,source)))
+
+(define-obsolete-variable-alias 'lsp-print-io 'lsp-log-io "lsp-mode 6.1")
+
+(defcustom lsp-log-io nil
+ "If non-nil, log all messages from the language server to a *lsp-log* buffer."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defcustom lsp-log-max message-log-max
+ "Maximum number of lines to keep in the log buffer.
+If nil, disable message logging. If t, log messages but don’t truncate
+the buffer when it becomes large."
+ :group 'lsp-mode
+ :type '(choice (const :tag "Disable" nil)
+ (integer :tag "lines")
+ (const :tag "Unlimited" t))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-io-messages-max t
+ "Maximum number of messages that can be locked in a `lsp-io' buffer."
+ :group 'lsp-mode
+ :type '(choice (const :tag "Unlimited" t)
+ (integer :tag "Messages"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-keep-workspace-alive t
+ "If non nil keep workspace alive when the last workspace buffer is closed."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defcustom lsp-enable-snippet t
+ "Enable/disable snippet completion support."
+ :group 'lsp-completion
+ :type 'boolean)
+
+(defcustom lsp-enable-folding t
+ "Enable/disable code folding support."
+ :group 'lsp-mode
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(define-obsolete-variable-alias 'lsp-enable-semantic-highlighting 'lsp-semantic-tokens-enable "lsp-mode 7.1")
+
+(defcustom lsp-semantic-tokens-enable nil
+ "Enable/disable support for semantic tokens.
+As defined by the Language Server Protocol 3.16."
+ :group 'lsp-semantic-tokens
+ :type 'boolean)
+
+(defcustom lsp-folding-range-limit nil
+ "The maximum number of folding ranges to receive from the language server."
+ :group 'lsp-mode
+ :type '(choice (const :tag "No limit." nil)
+ (integer :tag "Number of lines."))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-folding-line-folding-only nil
+ "If non-nil, only fold complete lines."
+ :group 'lsp-mode
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-client-packages
+ '(ccls lsp-actionscript lsp-ada lsp-angular lsp-bash lsp-beancount lsp-clangd lsp-clojure lsp-cmake
+ lsp-crystal lsp-csharp lsp-css lsp-d lsp-dart lsp-dhall lsp-dockerfile lsp-elm
+ lsp-elixir lsp-erlang lsp-eslint lsp-fortran lsp-fsharp lsp-gdscript lsp-go
+ lsp-hack lsp-grammarly lsp-groovy lsp-haskell lsp-haxe lsp-java lsp-javascript lsp-json
+ lsp-kotlin lsp-ltex lsp-lua lsp-markdown lsp-nim lsp-nix lsp-metals lsp-ocaml lsp-perl lsp-php lsp-pwsh
+ lsp-pyls lsp-pylsp lsp-python-ms lsp-purescript lsp-r lsp-rf lsp-rust lsp-solargraph lsp-sorbet
+ lsp-tex lsp-terraform lsp-v lsp-vala lsp-verilog lsp-vetur lsp-vhdl lsp-vimscript lsp-xml
+ lsp-yaml lsp-sqls lsp-svelte lsp-steep lsp-zig)
+ "List of the clients to be automatically required."
+ :group 'lsp-mode
+ :type '(repeat symbol))
+
+(defcustom lsp-progress-via-spinner t
+ "If non-nil, display LSP $/progress reports via a spinner in the modeline."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defvar-local lsp--cur-workspace nil)
+
+(defvar-local lsp--cur-version 0)
+(defvar-local lsp--virtual-buffer-connections nil)
+(defvar-local lsp--virtual-buffer nil)
+(defvar lsp--virtual-buffer-mappings (ht))
+
+(defvar lsp--uri-file-prefix (pcase system-type
+ (`windows-nt "file:///")
+ (_ "file://"))
+ "Prefix for a file-uri.")
+
+(defvar-local lsp-buffer-uri nil
+ "If set, return it instead of calculating it using `buffer-file-name'.")
+
+(define-error 'lsp-error "Unknown lsp-mode error")
+(define-error 'lsp-empty-response-error
+ "Empty response from the language server" 'lsp-error)
+(define-error 'lsp-timed-out-error
+ "Timed out while waiting for a response from the language server" 'lsp-error)
+(define-error 'lsp-capability-not-supported
+ "Capability not supported by the language server" 'lsp-error)
+(define-error 'lsp-file-scheme-not-supported
+ "Unsupported file scheme" 'lsp-error)
+(define-error 'lsp-client-already-exists-error
+ "A client with this server-id already exists" 'lsp-error)
+(define-error 'lsp-no-code-actions
+ "No code actions" 'lsp-error)
+
+(defcustom lsp-auto-guess-root nil
+ "Automatically guess the project root using projectile/project.
+Do *not* use this setting unless you are familiar with `lsp-mode'
+internals and you are sure that all of your projects are
+following `projectile'/`project.el' conventions."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defcustom lsp-restart 'interactive
+ "Defines how server-exited events must be handled."
+ :group 'lsp-mode
+ :type '(choice (const interactive)
+ (const auto-restart)
+ (const ignore)))
+
+(defcustom lsp-session-file (expand-file-name (locate-user-emacs-file ".lsp-session-v1"))
+ "File where session information is stored."
+ :group 'lsp-mode
+ :type 'file)
+
+(defcustom lsp-auto-configure t
+ "Auto configure `lsp-mode' main features.
+When set to t `lsp-mode' will auto-configure completion,
+code-actions, breadcrumb, `flycheck', `flymake', `imenu', symbol highlighting,
+lenses, links, and so on.
+
+For finer granularity you may use `lsp-enable-*' properties."
+ :group 'lsp-mode
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-disabled-clients nil
+ "A list of disabled/blacklisted clients.
+Each entry in the list can be either:
+a symbol, the server-id for the LSP client, or
+a cons pair (MAJOR-MODE . CLIENTS), where MAJOR-MODE is the major-mode,
+and CLIENTS is either a client or a list of clients.
+
+This option can also be used as a file- or directory-local variable to
+disable a language server for individual files or directories/projects
+respectively."
+ :group 'lsp-mode
+ :type '(repeat (symbol))
+ :safe 'listp
+ :package-version '(lsp-mode . "6.1"))
+
+(defvar lsp-clients (make-hash-table :test 'eql)
+ "Hash table server-id -> client.
+It contains all of the clients that are currently registered.")
+
+(defvar lsp-enabled-clients nil
+ "List of clients allowed to be used for projects.
+When nil, all registered clients are considered candidates.")
+
+(defvar lsp-last-id 0
+ "Last request id.")
+
+(defcustom lsp-before-initialize-hook nil
+ "List of functions to be called before a Language Server has been initialized
+for a new workspace."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-after-initialize-hook nil
+ "List of functions to be called after a Language Server has been initialized
+for a new workspace."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-before-open-hook nil
+ "List of functions to be called before a new file with LSP support is opened."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-after-open-hook nil
+ "List of functions to be called after a new file with LSP support is opened."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-file-watchers t
+ "If non-nil lsp-mode will watch the files in the workspace if
+the server has requested that."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+;;;###autoload(put 'lsp-enable-file-watchers 'safe-local-variable #'booleanp)
+
+(define-obsolete-variable-alias 'lsp-file-watch-ignored 'lsp-file-watch-ignored-directories "7.1.0")
+
+(defcustom lsp-file-watch-ignored-directories
+ '(; SCM tools
+ "[/\\\\]\\.git\\'"
+ "[/\\\\]\\.github\\'"
+ "[/\\\\]\\.circleci\\'"
+ "[/\\\\]\\.hg\\'"
+ "[/\\\\]\\.bzr\\'"
+ "[/\\\\]_darcs\\'"
+ "[/\\\\]\\.svn\\'"
+ "[/\\\\]_FOSSIL_\\'"
+ ;; IDE or build tools
+ "[/\\\\]\\.idea\\'"
+ "[/\\\\]\\.ensime_cache\\'"
+ "[/\\\\]\\.eunit\\'"
+ "[/\\\\]node_modules"
+ "[/\\\\]\\.yarn\\'"
+ "[/\\\\]\\.fslckout\\'"
+ "[/\\\\]\\.tox\\'"
+ "[/\\\\]dist\\'"
+ "[/\\\\]dist-newstyle\\'"
+ "[/\\\\]\\.stack-work\\'"
+ "[/\\\\]\\.bloop\\'"
+ "[/\\\\]\\.metals\\'"
+ "[/\\\\]target\\'"
+ "[/\\\\]\\.ccls-cache\\'"
+ "[/\\\\]\\.vscode\\'"
+ ;; Autotools output
+ "[/\\\\]\\.deps\\'"
+ "[/\\\\]build-aux\\'"
+ "[/\\\\]autom4te.cache\\'"
+ "[/\\\\]\\.reference\\'"
+ ;; Clojure
+ "[/\\\\]\\.lsp\\'"
+ "[/\\\\]\\.clj-kondo\\'"
+ "[/\\\\]\\.shadow-cljs\\'"
+ "[/\\\\]\\.babel_cache\\'"
+ "[/\\\\]\\.cpcache\\'"
+ ;; .Net Core build-output
+ "[/\\\\]bin/Debug\\'"
+ "[/\\\\]obj\\'"
+ ;; OCaml and Dune
+ "[/\\\\]_opam\\'"
+ "[/\\\\]_build\\'"
+ ;; nix-direnv
+ "[/\\\\]\\.direnv\\'")
+ "List of regexps matching directory paths which won't be monitored when
+creating file watches. Customization of this variable is only honored at
+the global level or at a root of an lsp workspace."
+ :group 'lsp-mode
+ :type '(repeat string)
+ :package-version '(lsp-mode . "7.1.0"))
+
+(define-obsolete-function-alias 'lsp-file-watch-ignored 'lsp-file-watch-ignored-directories "7.0.1")
+
+(defun lsp-file-watch-ignored-directories ()
+ lsp-file-watch-ignored-directories)
+
+;; Allow lsp-file-watch-ignored-directories as a file or directory-local variable
+(put 'lsp-file-watch-ignored-directories 'safe-local-variable 'lsp--string-listp)
+
+(defcustom lsp-file-watch-ignored-files
+ '(
+ ;; Flycheck tempfiles
+ "[/\\\\]flycheck_[^/\\\\]+\\'"
+ ;; lockfiles
+ "[/\\\\]\\.#[^/\\\\]+\\'"
+ ;; backup files
+ "[/\\\\][^/\\\\]+~\\'" )
+ "List of regexps matching files for which change events will
+not be sent to the server.
+
+This setting has no impact on whether a file-watch is created for
+a directory; it merely prevents notifications pertaining to
+matched files from being sent to the server. To prevent a
+file-watch from being created for a directory, customize
+`lsp-file-watch-ignored-directories'
+
+Customization of this variable is only honored at the global
+level or at a root of an lsp workspace."
+ :group 'lsp-mode
+ :type '(repeat string)
+ :package-version '(lsp-mode . "7.1.0"))
+
+;; Allow lsp-file-watch-ignored-files as a file or directory-local variable
+(put 'lsp-file-watch-ignored-files 'safe-local-variable 'lsp--string-listp)
+
+(defcustom lsp-after-uninitialized-functions nil
+ "List of functions to be called after a Language Server has been uninitialized."
+ :type 'hook
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.3"))
+
+(defconst lsp--sync-none 0)
+(defconst lsp--sync-full 1)
+(defconst lsp--sync-incremental 2)
+
+(defcustom lsp-debounce-full-sync-notifications t
+ "If non-nil debounce full sync events.
+This flag affects only servers which do not support incremental updates."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-debounce-full-sync-notifications-interval 1.0
+ "Time to wait before sending full sync synchronization after buffer modification."
+ :type 'float
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+
+(defvar lsp--stderr-index 0)
+
+(defvar lsp--delayed-requests nil)
+(defvar lsp--delay-timer nil)
+
+(defcustom lsp-document-sync-method nil
+ "How to sync the document with the language server."
+ :type '(choice (const :tag "Documents should not be synced at all." nil)
+ (const :tag "Documents are synced by always sending the full content of the document." lsp--sync-full)
+ (const :tag "Documents are synced by always sending incremental changes to the document." lsp--sync-incremental)
+ (const :tag "Use the method recommended by the language server." nil))
+ :group 'lsp-mode)
+
+(defcustom lsp-auto-execute-action t
+ "Auto-execute single action."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-links t
+ "If non-nil, all references to links in a file will be made clickable, if
+supported by the language server."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-enable-imenu t
+ "If non-nil, automatically enable `imenu' integration when server provides
+`textDocument/documentSymbol'."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-enable-dap-auto-configure t
+ "If non-nil, enable `dap-auto-configure-mode`."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "7.0"))
+
+(defcustom lsp-eldoc-enable-hover t
+ "If non-nil, `eldoc' will display hover info when it is present."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-eldoc-render-all nil
+ "Display all of the info returned by document/onHover.
+If this is set to nil, `eldoc' will show only the symbol information."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(define-obsolete-variable-alias 'lsp-enable-completion-at-point
+ 'lsp-completion-enable "lsp-mode 7.0.1")
+
+(defcustom lsp-completion-enable t
+ "Enable `completion-at-point' integration."
+ :type 'boolean
+ :group 'lsp-completion)
+
+(defcustom lsp-enable-symbol-highlighting t
+ "Highlight references of the symbol at point."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-xref t
+ "Enable xref integration."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-indentation t
+ "Indent regions using the file formatting functionality provided by the
+language server."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-on-type-formatting t
+ "Enable `textDocument/onTypeFormatting' integration."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-enable-text-document-color t
+ "Enable `textDocument/documentColor' integration."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-before-save-edits t
+ "If non-nil, `lsp-mode' will apply edits suggested by the language server
+before saving a document."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defcustom lsp-after-apply-edits-hook nil
+ "Hooks to run when text edit is applied.
+It contains the operation source."
+ :type 'hook
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-modeline-code-actions-enable t
+ "Whether to show code actions on modeline."
+ :type 'boolean
+ :group 'lsp-modeline)
+
+(defcustom lsp-modeline-diagnostics-enable t
+ "Whether to show diagnostics on modeline."
+ :type 'boolean
+ :group 'lsp-modeline)
+
+(defcustom lsp-modeline-workspace-status-enable t
+ "Whether to show workspace status on modeline."
+ :type 'boolean
+ :group 'lsp-modeline
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-headerline-breadcrumb-enable t
+ "Whether to enable breadcrumb on headerline."
+ :type 'boolean
+ :group 'lsp-headerline)
+
+(defcustom lsp-configure-hook nil
+ "Hooks to run when `lsp-configure-buffer' is called."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-unconfigure-hook nil
+ "Hooks to run when `lsp-unconfig-buffer' is called."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-after-diagnostics-hook nil
+ "Hooks to run after diagnostics are received.
+Note: it runs only if the receiving buffer is open. Use
+`lsp-diagnostics-updated-hook'if you want to be notified when
+diagnostics have changed."
+ :type 'hook
+ :group 'lsp-mode)
+
+(define-obsolete-variable-alias 'lsp-after-diagnostics-hook
+ 'lsp-diagnostics-updated-hook "lsp-mode 6.4")
+
+(defcustom lsp-diagnostics-updated-hook nil
+ "Hooks to run after diagnostics are received."
+ :type 'hook
+ :group 'lsp-mode)
+
+(define-obsolete-variable-alias 'lsp-workspace-folders-changed-hook
+ 'lsp-workspace-folders-changed-functions "lsp-mode 6.3")
+
+(defcustom lsp-workspace-folders-changed-functions nil
+ "Hooks to run after the folders has changed.
+The hook will receive two parameters list of added and removed folders."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-eldoc-hook '(lsp-hover)
+ "Hooks to run for eldoc."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-before-apply-edits-hook nil
+ "Hooks to run before applying edits."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defgroup lsp-imenu nil
+ "LSP Imenu."
+ :group 'lsp-mode
+ :tag "LSP Imenu")
+
+(defcustom lsp-imenu-show-container-name t
+ "Display the symbol's container name in an imenu entry."
+ :type 'boolean
+ :group 'lsp-imenu)
+
+(defcustom lsp-imenu-container-name-separator "/"
+ "Separator string to use to separate the container name from the symbol while
+displaying imenu entries."
+ :type 'string
+ :group 'lsp-imenu)
+
+(defcustom lsp-imenu-sort-methods '(kind name)
+ "How to sort the imenu items.
+
+The value is a list of `kind' `name' or `position'. Priorities
+are determined by the index of the element."
+ :type '(repeat (choice (const name)
+ (const position)
+ (const kind)))
+ :group 'lsp-imenu)
+
+(defcustom lsp-imenu-index-symbol-kinds nil
+ "Which symbol kinds to show in imenu."
+ :type '(repeat (choice (const :tag "Miscellaneous" nil)
+ (const :tag "File" File)
+ (const :tag "Module" Module)
+ (const :tag "Namespace" Namespace)
+ (const :tag "Package" Package)
+ (const :tag "Class" Class)
+ (const :tag "Method" Method)
+ (const :tag "Property" Property)
+ (const :tag "Field" Field)
+ (const :tag "Constructor" Constuctor)
+ (const :tag "Enum" Enum)
+ (const :tag "Interface" Interface)
+ (const :tag "Function" Function)
+ (const :tag "Variable" Variable)
+ (const :tag "Constant" Constant)
+ (const :tag "String" String)
+ (const :tag "Number" Number)
+ (const :tag "Boolean" Boolean)
+ (const :tag "Array" Array)
+ (const :tag "Object" Object)
+ (const :tag "Key" Key)
+ (const :tag "Null" Null)
+ (const :tag "Enum Member" EnumMember)
+ (const :tag "Struct" Struct)
+ (const :tag "Event" Event)
+ (const :tag "Operator" Operator)
+ (const :tag "Type Parameter" TypeParameter)))
+ :group 'lsp-imenu)
+
+;; vibhavp: Should we use a lower value (5)?
+(defcustom lsp-response-timeout 10
+ "Number of seconds to wait for a response from the language server before
+timing out."
+ :type 'number
+ :group 'lsp-mode)
+
+(defcustom lsp-tcp-connection-timeout 2
+ "The timeout for tcp connection in seconds."
+ :type 'number
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.2"))
+
+(defconst lsp--imenu-compare-function-alist
+ (list (cons 'name #'lsp--imenu-compare-name)
+ (cons 'kind #'lsp--imenu-compare-kind)
+ (cons 'position #'lsp--imenu-compare-line-col))
+ "An alist of (METHOD . FUNCTION).
+METHOD is one of the symbols accepted by
+`lsp-imenu-sort-methods'.
+
+FUNCTION takes two hash tables representing DocumentSymbol. It
+returns a negative number, 0, or a positive number indicating
+whether the first parameter is less than, equal to, or greater
+than the second parameter.")
+
+(defcustom lsp-diagnostic-clean-after-change nil
+ "When non-nil, clean the diagnostics on change.
+
+Note that when that setting is nil, `lsp-mode' will show stale
+diagnostics until server publishes the new set of diagnostics"
+ :type 'boolean
+ :group 'lsp-diagnostics
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-server-trace nil
+ "Request tracing on the server side.
+The actual trace output at each level depends on the language server in use.
+Changes take effect only when a new session is started."
+ :type '(choice (const :tag "Disabled" "off")
+ (const :tag "Messages only" "messages")
+ (const :tag "Verbose" "verbose")
+ (const :tag "Default (disabled)" nil))
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.1"))
+
+(defvar lsp-language-id-configuration '((".*\\.vue$" . "vue")
+ (".*\\.tsx$" . "typescriptreact")
+ (".*\\.ts$" . "typescript")
+ (".*\\.jsx$" . "javascriptreact")
+ (".*\\.js$" . "javascript")
+ (".*\\.xml$" . "xml")
+ (".*\\.hx$" . "haxe")
+ (".*\\.lua$" . "lua")
+ (".*\\.sql$" . "sql")
+ (".*\\.html$" . "html")
+ (".*\\.css" . "css")
+ (".*/settings.json$" . "jsonc")
+ (".*\\.json$" . "json")
+ (".*\\.jsonc$" . "jsonc")
+ (".*\\.php$" . "php")
+ (".*\\.svelte$" . "svelte")
+ (ada-mode . "ada")
+ (nxml-mode . "xml")
+ (sql-mode . "sql")
+ (vimrc-mode . "vim")
+ (sh-mode . "shellscript")
+ (scala-mode . "scala")
+ (julia-mode . "julia")
+ (clojure-mode . "clojure")
+ (clojurec-mode . "clojure")
+ (clojurescript-mode . "clojurescript")
+ (java-mode . "java")
+ (jdee-mode . "java")
+ (groovy-mode . "groovy")
+ (python-mode . "python")
+ (cython-mode . "python")
+ (lsp--render-markdown . "markdown")
+ (rust-mode . "rust")
+ (rustic-mode . "rust")
+ (kotlin-mode . "kotlin")
+ (css-mode . "css")
+ (less-mode . "less")
+ (less-css-mode . "less")
+ (lua-mode . "lua")
+ (sass-mode . "sass")
+ (scss-mode . "scss")
+ (xml-mode . "xml")
+ (c-mode . "c")
+ (c++-mode . "cpp")
+ (objc-mode . "objective-c")
+ (html-mode . "html")
+ (sgml-mode . "html")
+ (mhtml-mode . "html")
+ (go-dot-mod-mode . "go.mod")
+ (go-mode . "go")
+ (haskell-mode . "haskell")
+ (hack-mode . "hack")
+ (php-mode . "php")
+ (powershell-mode . "powershell")
+ (powershell-mode . "PowerShell")
+ (json-mode . "json")
+ (jsonc-mode . "jsonc")
+ (rjsx-mode . "javascript")
+ (js2-mode . "javascript")
+ (js-mode . "javascript")
+ (typescript-mode . "typescript")
+ (fsharp-mode . "fsharp")
+ (reason-mode . "reason")
+ (caml-mode . "ocaml")
+ (tuareg-mode . "ocaml")
+ (swift-mode . "swift")
+ (elixir-mode . "elixir")
+ (conf-javaprop-mode . "spring-boot-properties")
+ (yaml-mode . "spring-boot-properties-yaml")
+ (ruby-mode . "ruby")
+ (enh-ruby-mode . "ruby")
+ (fortran-mode . "fortran")
+ (f90-mode . "fortran")
+ (elm-mode . "elm")
+ (dart-mode . "dart")
+ (erlang-mode . "erlang")
+ (dockerfile-mode . "dockerfile")
+ (csharp-mode . "csharp")
+ (csharp-tree-sitter-mode . "csharp")
+ (plain-tex-mode . "plaintex")
+ (latex-mode . "latex")
+ (v-mode . "v")
+ (vhdl-mode . "vhdl")
+ (verilog-mode . "verilog")
+ (terraform-mode . "terraform")
+ (ess-julia-mode . "julia")
+ (ess-r-mode . "r")
+ (crystal-mode . "crystal")
+ (nim-mode . "nim")
+ (dhall-mode . "dhall")
+ (cmake-mode . "cmake")
+ (purescript-mode . "purescript")
+ (gdscript-mode . "gdscript")
+ (perl-mode . "perl")
+ (cperl-mode . "perl")
+ (robot-mode . "robot")
+ (racket-mode . "racket")
+ (nix-mode . "nix")
+ (prolog-mode . "prolog")
+ (vala-mode . "vala")
+ (actionscript-mode . "actionscript")
+ (d-mode . "d")
+ (zig-mode . "zig")
+ (text-mode . "plaintext")
+ (markdown-mode . "markdown")
+ (beancount-mode . "beancount"))
+ "Language id configuration.")
+
+(defvar lsp--last-active-workspaces nil
+ "Keep track of last active workspace.
+We want to try the last workspace first when jumping into a library
+directory")
+
+(defvar lsp-method-requirements
+ '(("textDocument/callHierarchy" :capability :callHierarchyProvider)
+ ("textDocument/codeAction" :capability :codeActionProvider)
+ ("codeAction/resolve"
+ :check-command (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp:code-action-options-resolve-provider?
+ (or (lsp--capability :codeActionProvider)
+ (when-let ((maybe-capability (lsp--registered-capability "textDocument/codeAction"))
+ (capability-options (lsp--registered-capability-options maybe-capability)))
+ capability-options))))))
+ ("textDocument/codeLens" :capability :codeLensProvider)
+ ("textDocument/completion" :capability :completionProvider)
+ ("completionItem/resolve"
+ :check-command (lambda (wk)
+ (with-lsp-workspace wk
+ (lsp:completion-options-resolve-provider?
+ (lsp--capability :completionProvider)))))
+ ("textDocument/declaration" :capability :declarationProvider)
+ ("textDocument/definition" :capability :definitionProvider)
+ ("textDocument/documentColor" :capability :colorProvider)
+ ("textDocument/documentLink" :capability :documentLinkProvider)
+ ("textDocument/documentHighlight" :capability :documentHighlightProvider)
+ ("textDocument/documentSymbol" :capability :documentSymbolProvider)
+ ("textDocument/foldingRange" :capability :foldingRangeProvider)
+ ("textDocument/formatting" :capability :documentFormattingProvider)
+ ("textDocument/hover" :capability :hoverProvider)
+ ("textDocument/implementation" :capability :implementationProvider)
+ ("textDocument/onTypeFormatting" :capability :documentOnTypeFormattingProvider)
+ ("textDocument/prepareRename"
+ :check-command (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp:rename-options-prepare-provider?
+ (or (lsp--capability :renameProvider)
+ (when-let ((maybe-capability (lsp--registered-capability "textDocument/rename")))
+ (lsp--registered-capability-options maybe-capability)))))))
+ ("textDocument/rangeFormatting" :capability :documentRangeFormattingProvider)
+ ("textDocument/references" :capability :referencesProvider)
+ ("textDocument/rename" :capability :renameProvider)
+ ("textDocument/selectionRange" :capability :selectionRangeProvider)
+ ("textDocument/semanticTokens" :capability :semanticTokensProvider)
+ ("textDocument/semanticTokensFull"
+ :check-command (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp-get (lsp--capability :semanticTokensProvider) :full))))
+ ("textDocument/semanticTokensFull/Delta"
+ :check-command (lambda (workspace)
+ (with-lsp-workspace workspace
+ (let ((capFull (lsp-get (lsp--capability :semanticTokensProvider) :full)))
+ (and (not (booleanp capFull)) (lsp-get capFull :delta))))))
+ ("textDocument/semanticTokensRangeProvider"
+ :check-command (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp-get (lsp--capability :semanticTokensProvider) :range))))
+ ("textDocument/signatureHelp" :capability :signatureHelpProvider)
+ ("textDocument/typeDefinition" :capability :typeDefinitionProvider)
+ ("workspace/executeCommand" :capability :executeCommandProvider)
+ ("workspace/symbol" :capability :workspaceSymbolProvider))
+
+ "Map methods to requirements.
+It is used by request-sending functions to determine which server
+must be used for handling a particular message.")
+
+(defconst lsp--file-change-type
+ `((created . 1)
+ (changed . 2)
+ (deleted . 3)))
+
+(defconst lsp--watch-kind
+ `((create . 1)
+ (change . 2)
+ (delete . 4)))
+
+(defvar lsp-window-body-width 40
+ "Window body width when rendering doc.")
+
+(defface lsp-face-highlight-textual
+ '((t :inherit highlight))
+ "Face used for textual occurrences of symbols."
+ :group 'lsp-mode)
+
+(defface lsp-face-highlight-read
+ '((t :inherit highlight :underline t))
+ "Face used for highlighting symbols being read."
+ :group 'lsp-mode)
+
+(defface lsp-face-highlight-write
+ '((t :inherit highlight :weight bold))
+ "Face used for highlighting symbols being written to."
+ :group 'lsp-mode)
+
+(define-obsolete-variable-alias 'lsp-lens-auto-enable
+ 'lsp-lens-enable "lsp-mode 7.0.1")
+
+(defcustom lsp-lens-enable nil
+ "Auto enable lenses if server supports."
+ :group 'lsp-lens
+ :type 'boolean
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-symbol-highlighting-skip-current nil
+ "If non-nil skip current symbol when setting symbol highlights."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defcustom lsp-file-watch-threshold 1000
+ "Show warning if the files to watch are more than.
+Set to nil to disable the warning."
+ :type 'number
+ :group 'lsp-mode)
+;;;###autoload(put 'lsp-file-watch-threshold 'safe-local-variable (lambda (i) (or (numberp i) (not i))))
+
+(defvar lsp-custom-markup-modes
+ '((rust-mode "no_run" "rust,no_run" "rust,ignore" "rust,should_panic"))
+ "Mode to uses with markdown code blocks.
+They are added to `markdown-code-lang-modes'")
+
+(defcustom lsp-signature-render-documentation t
+ "Display signature documentation in `eldoc'."
+ :type 'boolean
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-signature-auto-activate '(:on-trigger-char :on-server-request)
+ "Auto activate signature conditions."
+ :type '(repeat (choice (const :tag "On trigger chars pressed." :on-trigger-char)
+ (const :tag "After selected completion." :after-completion)
+ (const :tag "When the server has sent show signature help." :on-server-request)))
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-signature-doc-lines 20
+ "If number, limit the number of lines to show in the docs."
+ :type 'number
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-signature-function 'lsp-lv-message
+ "The function used for displaying signature info.
+It will be called with one param - the signature info. When
+called with nil the signature info must be cleared."
+ :type 'function
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-keymap-prefix "s-l"
+ "LSP-mode keymap prefix."
+ :group 'lsp-mode
+ :type 'string
+ :package-version '(lsp-mode . "6.3"))
+
+(defvar-local lsp--buffer-workspaces ()
+ "List of the buffer workspaces.")
+
+(defvar lsp--session nil
+ "Contain the `lsp-session' for the current Emacs instance.")
+
+(defvar lsp--tcp-port 10000)
+
+(defvar lsp--client-packages-required nil
+ "If nil, `lsp-client-packages' are yet to be required.")
+
+(defvar lsp--tcp-server-port 0
+ "The server socket which is opened when using `lsp-tcp-server' (a server
+socket is opened in Emacs and the language server connects to it). The
+default value of 0 ensures that a random high port is used. Set it to a positive
+integer to use a specific port.")
+
+(defvar lsp--tcp-server-wait-seconds 10
+ "Wait this amount of time for the client to connect to our server socket
+when using `lsp-tcp-server'.")
+
+(defvar-local lsp--document-symbols nil
+ "The latest document symbols.")
+
+(defvar-local lsp--document-selection-range-cache nil
+ "The document selection cache.")
+
+(defvar-local lsp--document-symbols-request-async nil
+ "If non-nil, request document symbols asynchronously.")
+
+(defvar-local lsp--document-symbols-tick -1
+ "The value of `buffer-chars-modified-tick' when document
+ symbols were last retrieved.")
+
+(defvar-local lsp--have-document-highlights nil
+ "Set to `t' on symbol highlighting, cleared on
+`lsp--cleanup-highlights-if-needed'. Checking a separately
+defined flag is substantially faster than unconditionally
+calling `remove-overlays'.")
+
+;; Buffer local variable for storing number of lines.
+(defvar lsp--log-lines)
+
+(defvar-local lsp--eldoc-saved-message nil)
+
+(defvar lsp--on-change-timer nil)
+(defvar lsp--on-idle-timer nil)
+
+(defvar-local lsp--signature-last nil)
+(defvar-local lsp--signature-last-index nil)
+(defvar lsp--signature-last-buffer nil)
+
+(defvar-local lsp--virtual-buffer-point-max nil)
+
+(cl-defgeneric lsp-execute-command (server command arguments)
+ "Ask SERVER to execute COMMAND with ARGUMENTS.")
+
+(defun lsp-elt (sequence n)
+ "Return Nth element of SEQUENCE or nil if N is out of range."
+ (cond
+ ((listp sequence) (elt sequence n))
+ ((arrayp sequence)
+ (and (> (length sequence) n) (aref sequence n)))
+ (t (and (> (length sequence) n) (elt sequence n)))))
+
+;; define seq-first and seq-rest for older emacs
+(defun lsp-seq-first (sequence)
+ "Return the first element of SEQUENCE."
+ (lsp-elt sequence 0))
+
+(defun lsp-seq-rest (sequence)
+ "Return a sequence of the elements of SEQUENCE except the first one."
+ (seq-drop sequence 1))
+
+(defun lsp--string-listp (sequence)
+ "Return t if all elements of SEQUENCE are strings, else nil."
+ (not (seq-find (lambda (x) (not (stringp x))) sequence)))
+
+(defun lsp--string-vector-p (candidate)
+ "Returns true if CANDIDATE is a vector data structure and
+every element of it is of type string, else nil."
+ (and
+ (vectorp candidate)
+ (seq-every-p #'stringp candidate)))
+
+(make-obsolete 'lsp--string-vector-p nil "lsp-mode 7.1")
+
+(defun lsp--editable-vector-match (widget value)
+ "Function for `lsp-editable-vector' :match."
+ ;; Value must be a list or a vector and all the members must match the type.
+ (and (or (listp value) (vectorp value))
+ (length (cdr (lsp--editable-vector-match-inline widget value)))))
+
+(defun lsp--editable-vector-match-inline (widget value)
+ "Value for `lsp-editable-vector' :match-inline."
+ (let ((type (nth 0 (widget-get widget :args)))
+ (ok t)
+ found)
+ (while (and value ok)
+ (let ((answer (widget-match-inline type value)))
+ (if answer
+ (let ((head (if (vectorp answer) (aref answer 0) (car answer)))
+ (tail (if (vectorp answer) (seq-drop 1 answer) (cdr answer))))
+ (setq found (append found head)
+ value tail))
+ (setq ok nil))))
+ (cons found value)))
+
+(defun lsp--editable-vector-value-to-external (_widget internal-value)
+ "Convert the internal list value to a vector."
+ (if (listp internal-value)
+ (apply 'vector internal-value)
+ internal-value))
+
+(defun lsp--editable-vector-value-to-internal (_widget external-value)
+ "Convert the external vector value to a list."
+ (if (vectorp external-value)
+ (append external-value nil)
+ external-value))
+
+(define-widget 'lsp--editable-vector 'editable-list
+ "A subclass of `editable-list' that accepts and returns a
+vector instead of a list."
+ :value-to-external 'lsp--editable-vector-value-to-external
+ :value-to-internal 'lsp--editable-vector-value-to-internal
+ :match 'lsp--editable-vector-match
+ :match-inline 'lsp--editable-vector-match-inline)
+
+(define-widget 'lsp-repeatable-vector 'lsp--editable-vector
+ "A variable length homogeneous vector."
+ :tag "Repeat"
+ :format "%{%t%}:\n%v%i\n")
+
+(define-widget 'lsp-string-vector 'lazy
+ "A vector of zero or more elements, every element of which is a string.
+Appropriate for any language-specific `defcustom' that needs to
+serialize as a JSON array of strings.
+
+Deprecated. Use `lsp-repeatable-vector' instead. "
+ :offset 4
+ :tag "Vector"
+ :type '(lsp-repeatable-vector string))
+
+(make-obsolete 'lsp-string-vector nil "lsp-mode 7.1")
+
+(defvar lsp--show-message t
+ "If non-nil, show debug message from `lsp-mode'.")
+
+(defun lsp--message (format &rest args)
+ "Wrapper for `message'
+
+We `inhibit-message' the message when the cursor is in the
+minibuffer and when emacs version is before emacs 27 due to the
+fact that we often use `lsp--info', `lsp--warn' and `lsp--error'
+in async context and the call to these function is removing the
+minibuffer prompt. The issue with async messages is already fixed
+in emacs 27.
+
+See #2049"
+ (when lsp--show-message
+ (let ((inhibit-message (and (minibufferp)
+ (version< emacs-version "27.0"))))
+ (apply #'message format args))))
+
+(defun lsp--info (format &rest args)
+ "Display lsp info message with FORMAT with ARGS."
+ (lsp--message "%s :: %s" (propertize "LSP" 'face 'success) (apply #'format format args)))
+
+(defun lsp--warn (format &rest args)
+ "Display lsp warn message with FORMAT with ARGS."
+ (lsp--message "%s :: %s" (propertize "LSP" 'face 'warning) (apply #'format format args)))
+
+(defun lsp--error (format &rest args)
+ "Display lsp error message with FORMAT with ARGS."
+ (lsp--message "%s :: %s" (propertize "LSP" 'face 'error) (apply #'format format args)))
+
+(defun lsp--eldoc-message (&optional msg)
+ "Show MSG in eldoc."
+ (setq lsp--eldoc-saved-message msg)
+ (run-with-idle-timer 0 nil (lambda ()
+ ;; XXX: new eldoc in Emacs 28
+ ;; recommends running the hook variable
+ ;; `eldoc-documentation-functions'
+ ;; instead of using eldoc-message
+ (with-no-warnings
+ (eldoc-message msg)))))
+
+(defun lsp-log (format &rest args)
+ "Log message to the ’*lsp-log*’ buffer.
+
+FORMAT and ARGS i the same as for `message'."
+ (when lsp-log-max
+ (let ((log-buffer (get-buffer "*lsp-log*"))
+ (inhibit-read-only t))
+ (unless log-buffer
+ (setq log-buffer (get-buffer-create "*lsp-log*"))
+ (with-current-buffer log-buffer
+ (buffer-disable-undo)
+ (view-mode 1)
+ (set (make-local-variable 'lsp--log-lines) 0)))
+ (with-current-buffer log-buffer
+ (save-excursion
+ (let* ((message (apply 'format format args))
+ ;; Count newlines in message.
+ (newlines (1+ (cl-loop with start = 0
+ for count from 0
+ while (string-match "\n" message start)
+ do (setq start (match-end 0))
+ finally return count))))
+ (goto-char (point-max))
+
+ ;; in case the buffer is not empty insert before last \n to preserve
+ ;; the point position(in case it is in the end)
+ (if (eq (point) (point-min))
+ (progn
+ (insert "\n")
+ (backward-char))
+ (backward-char)
+ (insert "\n"))
+ (insert message)
+
+ (setq lsp--log-lines (+ lsp--log-lines newlines))
+
+ (when (and (integerp lsp-log-max) (> lsp--log-lines lsp-log-max))
+ (let ((to-delete (- lsp--log-lines lsp-log-max)))
+ (goto-char (point-min))
+ (forward-line to-delete)
+ (delete-region (point-min) (point))
+ (setq lsp--log-lines lsp-log-max)))))))))
+
+(defalias 'lsp-message 'lsp-log)
+
+(defalias 'lsp-ht 'ht)
+
+(defalias 'lsp-file-local-name 'file-local-name)
+
+(defun lsp-f-canonical (file-name)
+ "Return the canonical FILE-NAME, without a trailing slash."
+ (directory-file-name (expand-file-name file-name)))
+
+(defalias 'lsp-canonical-file-name 'lsp-f-canonical)
+
+(defun lsp-f-same? (path-a path-b)
+ "Return t if PATH-A and PATH-B are references to the same file.
+Symlinks are not followed."
+ (when (and (f-exists? path-a)
+ (f-exists? path-b))
+ (equal
+ (lsp-f-canonical (directory-file-name (f-expand path-a)))
+ (lsp-f-canonical (directory-file-name (f-expand path-b))))))
+
+(defun lsp-f-parent (path)
+ "Return the parent directory to PATH.
+Symlinks are not followed."
+ (let ((parent (file-name-directory
+ (directory-file-name (f-expand path default-directory)))))
+ (unless (lsp-f-same? path parent)
+ (if (f-relative? path)
+ (f-relative parent)
+ (directory-file-name parent)))))
+
+(defun lsp-f-ancestor-of? (path-a path-b)
+ "Return t if PATH-A is an ancestor of PATH-B.
+Symlinks are not followed."
+ (unless (lsp-f-same? path-a path-b)
+ (s-prefix? (concat (lsp-f-canonical path-a) (f-path-separator))
+ (lsp-f-canonical path-b))))
+
+(defun lsp--merge-results (results method)
+ "Merge RESULTS by filtering the empty hash-tables and merging
+the lists according to METHOD."
+ (pcase (--map (if (vectorp it)
+ (append it nil) it)
+ (-filter #'identity results))
+ (`() ())
+ ;; only one result - simply return it
+ (`(,fst) fst)
+ ;; multiple results merge it based on strategy
+ (results
+ (pcase method
+ ("textDocument/hover" (pcase (seq-filter
+ (-compose #'not #'lsp-empty?)
+ results)
+ (`(,hover) hover)
+ (hovers (lsp-make-hover
+ :contents
+ (-mapcat
+ (-lambda ((&Hover :contents))
+ (if (and (sequencep contents)
+ (not (stringp contents)))
+ (append contents ())
+ (list contents)))
+ hovers)))))
+ ("textDocument/completion"
+ (lsp-make-completion-list
+ :is-incomplete (seq-some
+ #'lsp:completion-list-is-incomplete
+ results)
+ :items (cl-mapcan (lambda (it) (append (if (lsp-completion-list? it)
+ (lsp:completion-list-items it)
+ it)
+ nil))
+ results)))
+ ("completionItem/resolve"
+ (let ((item (cl-first results)))
+ (when-let ((details (seq-filter #'identity
+ (seq-map #'lsp:completion-item-detail? results))))
+ (lsp:set-completion-item-detail?
+ item
+ (string-join details " ")))
+ (when-let ((docs (seq-filter #'identity
+ (seq-map #'lsp:completion-item-documentation? results))))
+ (lsp:set-completion-item-documentation?
+ item
+ (lsp-make-markup-content
+ :kind (or (seq-some (lambda (it)
+ (when (equal (lsp:markup-content-kind it)
+ lsp/markup-kind-markdown)
+ lsp/markup-kind-markdown))
+ docs)
+ lsp/markup-kind-plain-text)
+ :value (string-join (seq-map (lambda (doc)
+ (or (lsp:markup-content-value doc)
+ (and (stringp doc) doc)))
+ docs)
+ "\n"))))
+ (when-let ((edits (seq-filter #'identity
+ (seq-map #'lsp:completion-item-additional-text-edits? results))))
+ (lsp:set-completion-item-additional-text-edits?
+ item
+ (cl-mapcan (lambda (it) (if (seqp it) it (list it))) edits)))
+ item))
+ (_ (cl-mapcan (lambda (it) (if (seqp it) it (list it))) results))))))
+
+(defun lsp--spinner-start ()
+ "Start spinner indication."
+ (condition-case _err (spinner-start 'progress-bar-filled) (error)))
+
+(defun lsp--propertize (str type)
+ "Propertize STR as per TYPE."
+ (propertize str 'face (alist-get type lsp--message-type-face)))
+
+(defun lsp-workspaces ()
+ "Return the lsp workspaces associated with the current project."
+ (if lsp--cur-workspace (list lsp--cur-workspace) lsp--buffer-workspaces))
+
+(defun lsp--completing-read (prompt collection transform-fn &optional predicate
+ require-match initial-input
+ hist def inherit-input-method)
+ "Wrap `completing-read' to provide transformation function.
+
+TRANSFORM-FN will be used to transform each of the items before displaying.
+
+PROMPT COLLECTION PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF
+INHERIT-INPUT-METHOD will be proxied to `completing-read' without changes."
+ (let* ((col (--map (cons (funcall transform-fn it) it) collection))
+ (completion (completing-read prompt col
+ predicate require-match initial-input hist
+ def inherit-input-method)))
+ (cdr (assoc completion col))))
+
+(defmacro lsp-with-current-buffer (buffer-id &rest body)
+ (declare (indent 1) (debug t))
+ `(if-let ((wcb (plist-get ,buffer-id :with-current-buffer)))
+ (with-lsp-workspaces (plist-get ,buffer-id :workspaces)
+ (funcall wcb (lambda () ,@body)))
+ (with-current-buffer ,buffer-id
+ ,@body)))
+
+(defvar lsp--throw-on-input nil
+ "Make `lsp-*-while-no-input' throws `input' on interrupted.")
+
+(defmacro lsp--catch (tag bodyform &rest handlers)
+ "Catch TAG thrown in BODYFORM.
+The return value from TAG will be handled in HANDLERS by `pcase'."
+ (declare (debug (form form &rest (pcase-PAT body))) (indent 2))
+ (let ((re-sym (make-symbol "re")))
+ `(let ((,re-sym (catch ,tag ,bodyform)))
+ (pcase ,re-sym
+ ,@handlers))))
+
+(defmacro lsp--while-no-input (&rest body)
+ "Wrap BODY in `while-no-input' and respecting `non-essential'.
+If `lsp--throw-on-input' is set, will throw if input is pending, else
+return value of `body' or nil if interrupted."
+ (declare (debug t) (indent 0))
+ `(if non-essential
+ (let ((res (while-no-input ,@body)))
+ (cond
+ ((and lsp--throw-on-input (equal res t))
+ (throw 'input :interrupted))
+ ((booleanp res) nil)
+ (t res)))
+ ,@body))
+
+;; A ‘lsp--client’ object describes the client-side behavior of a language
+;; server. It is used to start individual server processes, each of which is
+;; represented by a ‘lsp--workspace’ object. Client objects are normally
+;; created using ‘lsp-define-stdio-client’ or ‘lsp-define-tcp-client’. Each
+;; workspace refers to exactly one client, but there can be multiple workspaces
+;; for a single client.
+(cl-defstruct lsp--client
+ ;; ‘language-id’ is a function that receives a buffer as a single argument
+ ;; and should return the language identifier for that buffer. See
+ ;; https://microsoft.github.io/language-server-protocol/specification#textdocumentitem
+ ;; for a list of language identifiers. Also consult the documentation for
+ ;; the language server represented by this client to find out what language
+ ;; identifiers it supports or expects.
+ (language-id nil)
+
+ ;; ‘add-on?’ when set to t the server will be started no matter whether there
+ ;; is another server handling the same mode.
+ (add-on? nil)
+ ;; ‘new-connection’ is a function that should start a language server process
+ ;; and return a cons (COMMAND-PROCESS . COMMUNICATION-PROCESS).
+ ;; COMMAND-PROCESS must be a process object representing the server process
+ ;; just started. COMMUNICATION-PROCESS must be a process (including pipe and
+ ;; network processes) that ‘lsp-mode’ uses to communicate with the language
+ ;; server using the language server protocol. COMMAND-PROCESS and
+ ;; COMMUNICATION-PROCESS may be the same process; in that case
+ ;; ‘new-connection’ may also return that process as a single
+ ;; object. ‘new-connection’ is called with two arguments, FILTER and
+ ;; SENTINEL. FILTER should be used as process filter for
+ ;; COMMUNICATION-PROCESS, and SENTINEL should be used as process sentinel for
+ ;; COMMAND-PROCESS.
+ (new-connection nil)
+
+ ;; ‘ignore-regexps’ is a list of regexps. When a data packet from the
+ ;; language server matches any of these regexps, it will be ignored. This is
+ ;; intended for dealing with language servers that output non-protocol data.
+ (ignore-regexps nil)
+
+ ;; ‘ignore-messages’ is a list of regexps. When a message from the language
+ ;; server matches any of these regexps, it will be ignored. This is useful
+ ;; for filtering out unwanted messages; such as servers that send nonstandard
+ ;; message types, or extraneous log messages.
+ (ignore-messages nil)
+
+ ;; ‘notification-handlers’ is a hash table mapping notification method names
+ ;; (strings) to functions handling the respective notifications. Upon
+ ;; receiving a notification, ‘lsp-mode’ will call the associated handler
+ ;; function passing two arguments, the ‘lsp--workspace’ object and the
+ ;; deserialized notification parameters.
+ (notification-handlers (make-hash-table :test 'equal))
+
+ ;; ‘request-handlers’ is a hash table mapping request method names
+ ;; (strings) to functions handling the respective notifications. Upon
+ ;; receiving a request, ‘lsp-mode’ will call the associated handler function
+ ;; passing two arguments, the ‘lsp--workspace’ object and the deserialized
+ ;; request parameters.
+ (request-handlers (make-hash-table :test 'equal))
+
+ ;; ‘response-handlers’ is a hash table mapping integral JSON-RPC request
+ ;; identifiers for pending asynchronous requests to functions handling the
+ ;; respective responses. Upon receiving a response from the language server,
+ ;; ‘lsp-mode’ will call the associated response handler function with a
+ ;; single argument, the deserialized response parameters.
+ (response-handlers (make-hash-table :test 'eql))
+
+ ;; ‘prefix-function’ is called for getting the prefix for completion.
+ ;; The function takes no parameter and returns a cons (start . end) representing
+ ;; the start and end bounds of the prefix. If it's not set, the client uses a
+ ;; default prefix function."
+ (prefix-function nil)
+
+ ;; Contains mapping of scheme to the function that is going to be used to load
+ ;; the file.
+ (uri-handlers (make-hash-table :test #'equal))
+
+ ;; ‘action-handlers’ is a hash table mapping action to a handler function. It
+ ;; can be used in `lsp-execute-code-action' to determine whether the action
+ ;; current client is interested in executing the action instead of sending it
+ ;; to the server.
+ (action-handlers (make-hash-table :test 'equal))
+
+ ;; major modes supported by the client.
+ major-modes
+ ;; Function that will be called to decide if this language client
+ ;; should manage a particular buffer. The function will be passed
+ ;; the file name and major mode to inform the decision. Setting
+ ;; `activation-fn' will override `major-modes', if
+ ;; present.
+ activation-fn
+ ;; Break the tie when major-mode is supported by multiple clients.
+ (priority 0)
+ ;; Unique identifier for representing the client object.
+ server-id
+ ;; defines whether the client supports multi root workspaces.
+ multi-root
+ ;; Initialization options or a function that returns initialization options.
+ initialization-options
+ ;; Overrides semantic tokens faces for specific clients
+ semantic-tokens-faces-overrides
+ ;; Provides support for registering LSP Server specific capabilities.
+ custom-capabilities
+ ;; Function which returns the folders that are considered to be not projects but library files.
+ ;; The function accepts one parameter currently active workspace.
+ ;; See: https://github.com/emacs-lsp/lsp-mode/issues/225.
+ library-folders-fn
+ ;; function which will be called when opening file in the workspace to perform
+ ;; client specific initialization. The function accepts one parameter
+ ;; currently active workspace.
+ before-file-open-fn
+ ;; Function which will be called right after a workspace has been initialized.
+ initialized-fn
+ ;; ‘remote?’ indicate whether the client can be used for LSP server over TRAMP.
+ (remote? nil)
+
+ ;; ‘completion-in-comments?’ t if the client supports completion in comments.
+ (completion-in-comments? nil)
+
+ ;; ‘path->uri-fn’ the function to use for path->uri conversion for the client.
+ (path->uri-fn nil)
+
+ ;; ‘uri->path-fn’ the function to use for uri->path conversion for the client.
+ (uri->path-fn nil)
+ ;; Function that returns an environment structure that will be used
+ ;; to set some environment variables when starting the language
+ ;; server process. These environment variables enable some
+ ;; additional features in the language server. The environment
+ ;; structure is an alist of the form (KEY . VALUE), where KEY is a
+ ;; string (regularly in all caps), and VALUE may be a string, a
+ ;; boolean, or a sequence of strings.
+ environment-fn
+
+ ;; ‘after-open-fn’ workspace after open specific hooks.
+ (after-open-fn nil)
+
+ ;; ‘async-request-handlers’ is a hash table mapping request method names
+ ;; (strings) to functions handling the respective requests that may take
+ ;; time to finish. Upon receiving a request, ‘lsp-mode’ will call the
+ ;; associated handler function passing three arguments, the ‘lsp--workspace’
+ ;; object, the deserialized request parameters and the callback which accept
+ ;; result as its parameter.
+ (async-request-handlers (make-hash-table :test 'equal))
+ download-server-fn
+ download-in-progress?
+ buffers)
+
+(defun lsp-clients-executable-find (find-command &rest args)
+ "Finds an executable by invoking a search command.
+
+FIND-COMMAND is the executable finder that searches for the
+actual language server executable. ARGS is a list of arguments to
+give to FIND-COMMAND to find the language server. Returns the
+output of FIND-COMMAND if it exits successfully, nil otherwise.
+
+Typical uses include finding an executable by invoking 'find' in
+a project, finding LLVM commands on macOS with 'xcrun', or
+looking up project-specific language servers for projects written
+in the various dynamic languages, e.g. 'nvm', 'pyenv' and 'rbenv'
+etc."
+ (when-let* ((find-command-path (executable-find find-command))
+ (executable-path
+ (with-temp-buffer
+ (when (zerop (apply 'call-process find-command-path nil t nil args))
+ (buffer-substring-no-properties (point-min) (point-max))))))
+ (string-trim executable-path)))
+
+(defvar lsp--already-widened nil)
+
+(defmacro lsp-save-restriction-and-excursion (&rest form)
+ (declare (indent 0) (debug t))
+ `(if lsp--already-widened
+ (save-excursion ,@form)
+ (-let [lsp--already-widened t]
+ (save-restriction
+ (widen)
+ (save-excursion ,@form)))))
+
+;; from http://emacs.stackexchange.com/questions/8082/how-to-get-buffer-position-given-line-number-and-column-number
+(defun lsp--line-character-to-point (line character)
+ "Return the point for character CHARACTER on line LINE."
+ (or (lsp-virtual-buffer-call :line/character->point line character)
+ (let ((inhibit-field-text-motion t))
+ (lsp-save-restriction-and-excursion
+ (goto-char (point-min))
+ (forward-line line)
+ ;; server may send character position beyond the current line and we
+ ;; should fallback to line end.
+ (-let [line-end (line-end-position)]
+ (if (> character (- line-end (point)))
+ line-end
+ (forward-char character)
+ (point)))))))
+
+(lsp-defun lsp--position-to-point ((&Position :line :character))
+ "Convert `Position' object in PARAMS to a point."
+ (lsp--line-character-to-point line character))
+
+(lsp-defun lsp--range-to-region ((&RangeToPoint :start :end))
+ (cons start end))
+
+(lsp-defun lsp--range-text ((&RangeToPoint :start :end))
+ (buffer-substring start end))
+
+(lsp-defun lsp--find-wrapping-range ((&SelectionRange :parent? :range (&RangeToPoint :start :end)))
+ (cond
+ ((and
+ (region-active-p)
+ (<= start (region-beginning) end)
+ (<= start (region-end) end)
+ (or (not (= start (region-beginning)))
+ (not (= end (region-end)))))
+ (cons start end))
+ ((and (<= start (point) end)
+ (not (region-active-p)))
+ (cons start end))
+ (parent? (lsp--find-wrapping-range parent?))))
+
+(defun lsp--get-selection-range ()
+ (or
+ (-when-let ((cache . cache-tick) lsp--document-selection-range-cache)
+ (when (= cache-tick (buffer-modified-tick)) cache))
+ (let ((response (cl-first
+ (lsp-request
+ "textDocument/selectionRange"
+ (list :textDocument (lsp--text-document-identifier)
+ :positions (vector (lsp--cur-position)))))))
+ (setq lsp--document-selection-range-cache
+ (cons response (buffer-modified-tick)))
+ response)))
+
+(defun lsp-extend-selection ()
+ "Extend selection."
+ (interactive)
+ (unless (lsp--capability :selectionRangeProvider)
+ (signal 'lsp-capability-not-supported (list "selectionRangeProvider")))
+ (-when-let ((start . end) (lsp--find-wrapping-range (lsp--get-selection-range)))
+ (goto-char start)
+ (set-mark (point))
+ (goto-char end)
+ (exchange-point-and-mark)))
+
+(defun lsp-warn (message &rest args)
+ "Display a warning message made from (`format-message' MESSAGE ARGS...).
+This is equivalent to `display-warning', using `lsp-mode' as the type and
+`:warning' as the level."
+ (display-warning 'lsp-mode (apply #'format-message message args)))
+
+(defun lsp--get-uri-handler (scheme)
+ "Get uri handler for SCHEME in the current workspace."
+ (--some (gethash scheme (lsp--client-uri-handlers (lsp--workspace-client it)))
+ (or (lsp-workspaces) (lsp--session-workspaces (lsp-session)))))
+
+(defun lsp--fix-path-casing (path)
+ "On windows, downcases path because the windows file system is
+case-insensitive.
+
+On other systems, returns path without change."
+ (if (eq system-type 'windows-nt) (downcase path) path))
+
+(defun lsp--uri-to-path (uri)
+ "Convert URI to a file path."
+ (if-let ((fn (->> (lsp-workspaces)
+ (-keep (-compose #'lsp--client-uri->path-fn #'lsp--workspace-client))
+ (cl-first))))
+ (funcall fn uri)
+ (lsp--uri-to-path-1 uri)))
+
+(defun lsp-remap-path-if-needed (file-name)
+ (-if-let ((virtual-buffer &as &plist :buffer) (gethash file-name lsp--virtual-buffer-mappings))
+ (propertize (buffer-local-value 'buffer-file-name buffer)
+ 'lsp-virtual-buffer virtual-buffer)
+ file-name))
+
+(defun lsp--uri-to-path-1 (uri)
+ "Convert URI to a file path."
+ (let* ((url (url-generic-parse-url (url-unhex-string uri)))
+ (type (url-type url))
+ (file (decode-coding-string (url-filename url)
+ (or locale-coding-system 'utf-8)))
+ (file-name (if (and type (not (string= type "file")))
+ (if-let ((handler (lsp--get-uri-handler type)))
+ (funcall handler uri)
+ uri)
+ ;; `url-generic-parse-url' is buggy on windows:
+ ;; https://github.com/emacs-lsp/lsp-mode/pull/265
+ (or (and (eq system-type 'windows-nt)
+ (eq (elt file 0) ?\/)
+ (substring file 1))
+ file))))
+ (->> file-name
+ (concat (-some #'lsp--workspace-host-root (lsp-workspaces)))
+ (lsp-remap-path-if-needed))))
+
+(defun lsp--buffer-uri ()
+ "Return URI of the current buffer."
+ (or lsp-buffer-uri
+ (plist-get lsp--virtual-buffer :buffer-uri)
+ (lsp--path-to-uri
+ (or (buffer-file-name) (buffer-file-name (buffer-base-buffer))))))
+
+(defun lsp-register-client-capabilities (&rest _args)
+ "Implemented only to make `company-lsp' happy.
+DELETE when `lsp-mode.el' is deleted.")
+
+(defconst lsp--url-path-allowed-chars
+ (url--allowed-chars (append '(?/) url-unreserved-chars))
+ "`url-unreserved-chars' with additional delim ?/.
+This set of allowed chars is enough for hexifying local file paths.")
+
+(defun lsp--path-to-uri-1 (path)
+ (concat lsp--uri-file-prefix
+ (--> path
+ (expand-file-name it)
+ (or (file-remote-p it 'localname t) it)
+ (url-hexify-string it lsp--url-path-allowed-chars))))
+
+(defun lsp--path-to-uri (path)
+ "Convert PATH to a uri."
+ (if-let ((uri-fn (->> (lsp-workspaces)
+ (-keep (-compose #'lsp--client-path->uri-fn #'lsp--workspace-client))
+ (cl-first))))
+ (funcall uri-fn path)
+ (lsp--path-to-uri-1 path)))
+
+(defun lsp--string-match-any (regex-list str)
+ "Return the first regex, if any, within REGEX-LIST matching STR."
+ (--first (string-match it str) regex-list))
+
+(cl-defstruct lsp-watch
+ (descriptors (make-hash-table :test 'equal))
+ root-directory)
+
+(defun lsp--folder-watch-callback (event callback watch ignored-files ignored-directories)
+ (let ((file-name (cl-third event))
+ (event-type (cl-second event)))
+ (cond
+ ((and (file-directory-p file-name)
+ (equal 'created event-type)
+ (not (lsp--string-match-any ignored-directories file-name)))
+
+ (lsp-watch-root-folder (file-truename file-name) callback ignored-files ignored-directories watch)
+
+ ;; process the files that are already present in
+ ;; the directory.
+ (->> (directory-files-recursively file-name ".*" t)
+ (seq-do (lambda (f)
+ (unless (file-directory-p f)
+ (funcall callback (list nil 'created f)))))))
+ ((and (memq event-type '(created deleted changed))
+ (not (file-directory-p file-name))
+ (not (lsp--string-match-any ignored-files file-name)))
+ (funcall callback event))
+ ((and (memq event-type '(renamed))
+ (not (file-directory-p file-name))
+ (not (lsp--string-match-any ignored-files file-name)))
+ (funcall callback `(,(cl-first event) deleted ,(cl-third event)))
+ (funcall callback `(,(cl-first event) created ,(cl-fourth event)))))))
+
+(defun lsp--ask-about-watching-big-repo (number-of-directories dir)
+ "Ask the user if they want to watch NUMBER-OF-DIRECTORIES from a repository DIR.
+This is useful when there is a lot of files in a repository, as
+that may slow Emacs down. Returns t if the user wants to watch
+the entire repository, nil otherwise."
+ (prog1
+ (yes-or-no-p
+ (format
+ "Watching all the files in %s would require adding watches to %s directories, so watching the repo may slow Emacs down.
+Do you want to watch all files in %s? "
+ dir
+ number-of-directories
+ dir))
+ (lsp--info
+ (concat "You can configure this warning with the `lsp-enable-file-watchers' "
+ "and `lsp-file-watch-threshold' variables"))))
+
+
+(defun lsp--path-is-watchable-directory (path dir ignored-directories)
+ "Figure out whether PATH (inside of DIR) is meant to have a file watcher set.
+IGNORED-DIRECTORIES is a list of regexes to filter out directories we don't want to watch."
+ (let
+ ((full-path (f-join dir path)))
+ (and (f-dir-p full-path)
+ (not (equal path "."))
+ (not (equal path ".."))
+ (not (lsp--string-match-any ignored-directories full-path)))))
+
+
+(defun lsp--all-watchable-directories (dir ignored-directories)
+ "Traverse DIR recursively and return a list of paths that should have watchers set on them.
+IGNORED-DIRECTORIES will be used for exclusions"
+ (let* ((dir (if (f-symlink? dir)
+ (file-truename dir)
+ dir)))
+ (apply #'nconc
+ ;; the directory itself is assumed to be part of the set
+ (list dir)
+ ;; collect all subdirectories that are watchable
+ (-map
+ (lambda (path) (lsp--all-watchable-directories (f-join dir path) ignored-directories))
+ ;; but only look at subdirectories that are watchable
+ (-filter (lambda (path) (lsp--path-is-watchable-directory path dir ignored-directories))
+ (directory-files dir))))))
+
+(defun lsp-watch-root-folder (dir callback ignored-files ignored-directories &optional watch warn-big-repo?)
+ "Create recursive file notification watch in DIR.
+CALLBACK will be called when there are changes in any of
+the monitored files. WATCHES is a hash table directory->file
+notification handle which contains all of the watch that
+already have been created. Watches will not be created for
+any directory that matches any regex in IGNORED-DIRECTORIES.
+Watches will not be created for any file that matches any
+regex in IGNORED-FILES."
+ (let* ((dir (if (f-symlink? dir)
+ (file-truename dir)
+ dir))
+ (watch (or watch (make-lsp-watch :root-directory dir)))
+ (dirs-to-watch (lsp--all-watchable-directories dir ignored-directories)))
+ (lsp-log "Creating watchers for following %s folders:\n %s"
+ (length dirs-to-watch)
+ (s-join "\n " dirs-to-watch))
+ (when (or
+ (not warn-big-repo?)
+ (not lsp-file-watch-threshold)
+ (let ((number-of-directories (length dirs-to-watch)))
+ (or
+ (< number-of-directories lsp-file-watch-threshold)
+ (condition-case _err
+ (lsp--ask-about-watching-big-repo number-of-directories dir)
+ ('quit)))))
+ (dolist (current-dir dirs-to-watch)
+ (condition-case err
+ (progn
+ (puthash
+ current-dir
+ (file-notify-add-watch current-dir
+ '(change)
+ (lambda (event)
+ (lsp--folder-watch-callback event callback watch ignored-files ignored-directories)))
+ (lsp-watch-descriptors watch)))
+ (error (lsp-log "Failed to create a watch for %s: message" (error-message-string err)))
+ (file-missing (lsp-log "Failed to create a watch for %s: message" (error-message-string err))))))
+ watch))
+
+(defun lsp-kill-watch (watch)
+ "Delete WATCH."
+ (-> watch lsp-watch-descriptors hash-table-values (-each #'file-notify-rm-watch))
+ (ht-clear! (lsp-watch-descriptors watch)))
+
+(defun lsp-json-bool (val)
+ "Convert VAL to JSON boolean."
+ (if val t :json-false))
+
+(defmacro with-lsp-workspace (workspace &rest body)
+ "Helper macro for invoking BODY in WORKSPACE context."
+ (declare (debug (form body))
+ (indent 1))
+ `(let ((lsp--cur-workspace ,workspace)) ,@body))
+
+(defmacro with-lsp-workspaces (workspaces &rest body)
+ "Helper macro for invoking BODY against multiple WORKSPACES."
+ (declare (debug (form body))
+ (indent 1))
+ `(let ((lsp--buffer-workspaces ,workspaces)) ,@body))
+
+
+
+(defconst lsp-downstream-deps
+ '(;; external packages
+ ccls consult-lsp dap-mode helm-lsp lsp-dart lsp-docker lsp-focus lsp-grammarly
+ lsp-haskell lsp-ivy lsp-java lsp-javacomp lsp-jedi lsp-julia lsp-latex lsp-ltex
+ lsp-metals lsp-mssql lsp-origami lsp-p4 lsp-pascal lsp-pyre lsp-pyright
+ lsp-python-ms lsp-rescript lsp-sonarlint lsp-sourcekit lsp-tailwindcss lsp-treemacs
+ lsp-ui swift-helpful
+ ;; clients
+ lsp-actionscript lsp-ada lsp-angular lsp-bash lsp-beancount lsp-clangd
+ lsp-clojure lsp-cmake lsp-crystal lsp-csharp lsp-css lsp-d lsp-dhall
+ lsp-dockerfile lsp-elixir lsp-elm lsp-erlang lsp-eslint lsp-fortran lsp-fsharp lsp-gdscript
+ lsp-go lsp-groovy lsp-hack lsp-haxe lsp-html lsp-javascript lsp-json lsp-kotlin lsp-lua
+ lsp-markdown lsp-nim lsp-nix lsp-ocaml lsp-perl lsp-php lsp-prolog lsp-purescript lsp-pwsh
+ lsp-pyls lsp-pylsp lsp-racket lsp-r lsp-rf lsp-rust lsp-solargraph lsp-sorbet lsp-sqls
+ lsp-steep lsp-svelte lsp-terraform lsp-tex lsp-v lsp-vala lsp-verilog lsp-vetur lsp-vhdl
+ lsp-vimscript lsp-xml lsp-yaml lsp-zig)
+ "List of downstream deps.")
+
+(defmacro lsp-consistency-check (package)
+ `(defconst ,(intern (concat (symbol-name package)
+ "-plist-value-when-compiled"))
+ (eval-when-compile lsp-use-plists)))
+
+;; (mapc
+;; (lambda (package)
+;; (with-eval-after-load package
+;; (let ((symbol-name (intern
+;; (concat (symbol-name package)
+;; "-plist-value-when-compiled"))))
+;; (cond
+;; ((not (boundp symbol-name))
+;; (warn "We have detected that you are using version of %s that is not compatible with current version of lsp-mode.el, please update it." (propertize (symbol-name package)
+;; 'face 'bold)))
+;; ((not (eq (symbol-value symbol-name) lsp-use-plists))
+;; (warn "Package %s is inconsistent with lsp-mode.el. This is indication of race during installation. In order to solve that please delete all packages related to lsp-mode, restar Emacs and install them again." (propertize (symbol-name package) 'face 'bold)))))))
+;; lsp-downstream-deps)
+
+
+;; loading code-workspace files
+
+;;;###autoload
+(defun lsp-load-vscode-workspace (file)
+ "Load vscode workspace from FILE"
+ (interactive "fSelect file to import: ")
+ (mapc #'lsp-workspace-folders-remove (lsp-session-folders (lsp-session)))
+
+ (let ((dir (f-dirname file)))
+ (->> file
+ (json-read-file)
+ (alist-get 'folders)
+ (-map (-lambda ((&alist 'path))
+ (lsp-workspace-folders-add (expand-file-name path dir)))))))
+
+;;;###autoload
+(defun lsp-save-vscode-workspace (file)
+ "Save vscode workspace to FILE"
+ (interactive "FSelect file to save to: ")
+
+ (let ((json-encoding-pretty-print t))
+ (f-write-text (json-encode
+ `((folders . ,(->> (lsp-session)
+ (lsp-session-folders)
+ (--map `((path . ,it)))))))
+ 'utf-8
+ file)))
+
+
+(defmacro lsp-foreach-workspace (&rest body)
+ "Execute BODY for each of the current workspaces."
+ (declare (debug (form body)))
+ `(--map (with-lsp-workspace it ,@body) (lsp-workspaces)))
+
+(defmacro when-lsp-workspace (workspace &rest body)
+ "Helper macro for invoking BODY in WORKSPACE context if present."
+ (declare (debug (form body))
+ (indent 1))
+ `(when-let ((lsp--cur-workspace ,workspace)) ,@body))
+
+(lsp-defun lsp--window-show-message (_workspace (&ShowMessageRequestParams :message :type))
+ "Send the server's messages to log.
+PARAMS - the data sent from _WORKSPACE."
+ (funcall (cl-case type
+ (1 'lsp--error)
+ (2 'lsp--warn)
+ (t 'lsp--info))
+ "%s"
+ message))
+
+(lsp-defun lsp--window-log-message (workspace (&ShowMessageRequestParams :message :type))
+ "Send the server's messages to log.
+PARAMS - the data sent from WORKSPACE."
+ (ignore
+ (let ((client (lsp--workspace-client workspace)))
+ (when (or (not client)
+ (cl-notany (-rpartial #'string-match-p message)
+ (lsp--client-ignore-messages client)))
+ (lsp-log "%s" (lsp--propertize message type))))))
+
+(lsp-defun lsp--window-log-message-request ((&ShowMessageRequestParams :message :type :actions?))
+ "Display a message request to the user and send the user's selection back to the server."
+ (let* ((message (lsp--propertize message type))
+ (choices (seq-map #'lsp:message-action-item-title actions?)))
+ (if choices
+ (completing-read (concat message " ") (seq-into choices 'list) nil t)
+ (lsp-log message))))
+
+(defcustom lsp-progress-prefix " ⌛ "
+ "Progress prefix."
+ :group 'lsp-mode
+ :type 'string
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-progress-function #'lsp-on-progress-modeline
+ "Function for handling the progress notifications."
+ :group 'lsp-mode
+ :type '(choice
+ (const :tag "Use modeline" lsp-on-progress-modeline)
+ (const :tag "Legacy(uses either `progress-reporter' or `spinner' based on `lsp-progress-via-spinner')"
+ lsp-on-progress-legacy)
+ (const ignore :tag "Ignore")
+ (function :tag "Other function"))
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defun lsp--progress-status ()
+ "Returns the status of the progress for the current workspaces."
+ (-let ((progress-status
+ (s-join
+ "|"
+ (-keep
+ (lambda (workspace)
+ (let ((tokens (lsp--workspace-work-done-tokens workspace)))
+ (unless (ht-empty? tokens)
+ (mapconcat
+ (-lambda ((&WorkDoneProgressBegin :message? :title :percentage?))
+ (concat (if percentage?
+ (format "%s%%%% " percentage?)
+ "")
+ (or message? title)))
+ (ht-values tokens)
+ "|"))))
+ (lsp-workspaces)))))
+ (unless (s-blank? progress-status)
+ (concat lsp-progress-prefix progress-status))))
+
+(lsp-defun lsp-on-progress-modeline (workspace (&ProgressParams :token :value
+ (value &as &WorkDoneProgress :kind)))
+ "PARAMS contains the progress data.
+WORKSPACE is the workspace that contains the progress token."
+ (add-to-list 'global-mode-string '(t (:eval (lsp--progress-status))))
+ (pcase kind
+ ("begin" (lsp-workspace-set-work-done-token token value workspace))
+ ("report" (lsp-workspace-set-work-done-token token value workspace))
+ ("end" (lsp-workspace-rem-work-done-token token workspace)))
+ (force-mode-line-update))
+
+(lsp-defun lsp-on-progress-legacy (workspace (&ProgressParams :token :value
+ (value &as &WorkDoneProgress :kind)))
+ "PARAMS contains the progress data.
+WORKSPACE is the workspace that contains the progress token."
+ (pcase kind
+ ("begin"
+ (-let* (((&WorkDoneProgressBegin :title :percentage?) value)
+ (reporter
+ (if lsp-progress-via-spinner
+ (let* ((spinner-strings (alist-get 'progress-bar spinner-types))
+ ;; Set message as a tooltip for the spinner strings
+ (propertized-strings
+ (seq-map (lambda (string) (propertize string 'help-echo title))
+ spinner-strings))
+ (spinner-type (vconcat propertized-strings)))
+ ;; The progress relates to the server as a whole,
+ ;; display it on all buffers.
+ (mapcar (lambda (buffer)
+ (lsp-with-current-buffer buffer
+ (spinner-start spinner-type))
+ buffer)
+ (lsp--workspace-buffers workspace)))
+ (if percentage?
+ (make-progress-reporter title 0 100 percentage?)
+ ;; No percentage, just progress
+ (make-progress-reporter title nil nil)))))
+ (lsp-workspace-set-work-done-token token reporter workspace)))
+ ("report"
+ (when-let ((reporter (lsp-workspace-get-work-done-token token workspace)))
+ (unless lsp-progress-via-spinner
+ (progress-reporter-update reporter (lsp:work-done-progress-report-percentage? value)))))
+
+ ("end"
+ (when-let ((reporter (lsp-workspace-get-work-done-token token workspace)))
+ (if lsp-progress-via-spinner
+ (mapc (lambda (buffer)
+ (when (lsp-buffer-live-p buffer)
+ (lsp-with-current-buffer buffer
+ (spinner-stop))))
+ reporter)
+ (progress-reporter-done reporter))
+ (lsp-workspace-rem-work-done-token token workspace)))))
+
+
+;; diagnostics
+
+(defvar lsp-diagnostic-filter nil
+ "A a function which will be called with
+ `&PublishDiagnosticsParams' and `workspace' which can be used
+ to filter out the diagnostics. The function should return
+ `&PublishDiagnosticsParams'.
+
+Common usecase are:
+1. Filter the diagnostics for a particular language server.
+2. Filter out the diagnostics under specific level.")
+
+(defvar lsp-diagnostic-stats (ht))
+
+(defun lsp-diagnostics (&optional current-workspace?)
+ "Return the diagnostics from all workspaces."
+ (or (pcase (if current-workspace?
+ (lsp-workspaces)
+ (lsp--session-workspaces (lsp-session)))
+ (`() ())
+ (`(,workspace) (lsp--workspace-diagnostics workspace))
+ (`,workspaces (let ((result (make-hash-table :test 'equal)))
+ (mapc (lambda (workspace)
+ (->> workspace
+ (lsp--workspace-diagnostics)
+ (maphash (lambda (file-name diagnostics)
+ (puthash file-name
+ (append (gethash file-name result) diagnostics)
+ result)))))
+ workspaces)
+ result)))
+ (ht)))
+
+(defun lsp-diagnostics-stats-for (path)
+ "Get diagnostics statistics for PATH.
+The result format is vector [_ errors warnings infos hints] or nil."
+ (gethash (lsp--fix-path-casing path) lsp-diagnostic-stats))
+
+(defun lsp-diagnostics--update-path (path new-stats)
+ (let ((new-stats (copy-sequence new-stats))
+ (path (lsp--fix-path-casing (directory-file-name path))))
+ (if-let ((old-data (gethash path lsp-diagnostic-stats)))
+ (dotimes (idx 5)
+ (cl-callf + (aref old-data idx)
+ (aref new-stats idx)))
+ (puthash path new-stats lsp-diagnostic-stats))))
+
+(lsp-defun lsp--on-diagnostics-update-stats (workspace
+ (&PublishDiagnosticsParams :uri :diagnostics))
+ (let ((path (lsp--fix-path-casing (lsp--uri-to-path uri)))
+ (new-stats (make-vector 5 0)))
+ (mapc (-lambda ((&Diagnostic :severity?))
+ (cl-incf (aref new-stats (or severity? 1))))
+ diagnostics)
+ (when-let ((old-diags (gethash path (lsp--workspace-diagnostics workspace))))
+ (mapc (-lambda ((&Diagnostic :severity?))
+ (cl-decf (aref new-stats (or severity? 1))))
+ old-diags))
+ (lsp-diagnostics--update-path path new-stats)
+ (while (not (string= path (setf path (file-name-directory
+ (directory-file-name path)))))
+ (lsp-diagnostics--update-path path new-stats))))
+
+(defun lsp--on-diagnostics (workspace params)
+ "Callback for textDocument/publishDiagnostics.
+interface PublishDiagnosticsParams {
+ uri: string;
+ diagnostics: Diagnostic[];
+}
+PARAMS contains the diagnostics data.
+WORKSPACE is the workspace that contains the diagnostics."
+ (when lsp-diagnostic-filter
+ (setf params (funcall lsp-diagnostic-filter params workspace)))
+
+ (lsp--on-diagnostics-update-stats workspace params)
+
+ (-let* (((&PublishDiagnosticsParams :uri :diagnostics) params)
+ (lsp--virtual-buffer-mappings (ht))
+ (file (lsp--fix-path-casing (lsp--uri-to-path uri)))
+ (workspace-diagnostics (lsp--workspace-diagnostics workspace)))
+
+ (if (seq-empty-p diagnostics)
+ (remhash file workspace-diagnostics)
+ (puthash file (append diagnostics nil) workspace-diagnostics))
+
+ (run-hooks 'lsp-diagnostics-updated-hook)))
+
+(defun lsp-diagnostics--workspace-cleanup (workspace)
+ (->> workspace
+ (lsp--workspace-diagnostics)
+ (maphash (lambda (key _)
+ (lsp--on-diagnostics-update-stats
+ workspace
+ (lsp-make-publish-diagnostics-params
+ :uri (lsp--path-to-uri key)
+ :diagnostics [])))))
+ (clrhash (lsp--workspace-diagnostics workspace)))
+
+
+
+;; textDocument/foldingRange support
+
+(cl-defstruct lsp--folding-range beg end kind children)
+
+(defvar-local lsp--cached-folding-ranges nil)
+(defvar-local lsp--cached-nested-folding-ranges nil)
+
+(defun lsp--folding-range-width (range)
+ (- (lsp--folding-range-end range)
+ (lsp--folding-range-beg range)))
+
+(defun lsp--get-folding-ranges ()
+ "Get the folding ranges for the current buffer."
+ (unless (eq (buffer-chars-modified-tick) (car lsp--cached-folding-ranges))
+ (let* ((ranges (lsp-request "textDocument/foldingRange"
+ `(:textDocument ,(lsp--text-document-identifier))))
+ (sorted-line-col-pairs (->> ranges
+ (cl-mapcan (-lambda ((&FoldingRange :start-line
+ :start-character?
+ :end-line
+ :end-character?))
+ (list (cons start-line start-character?)
+ (cons end-line end-character?))))
+ (-sort #'lsp--line-col-comparator)))
+ (line-col-to-point-map (lsp--convert-line-col-to-points-batch
+ sorted-line-col-pairs)))
+ (setq lsp--cached-folding-ranges
+ (cons (buffer-chars-modified-tick)
+ (--> ranges
+ (seq-map (-lambda ((range &as
+ &FoldingRange :start-line
+ :start-character?
+ :end-line
+ :end-character?
+ :kind?))
+ (make-lsp--folding-range
+ :beg (ht-get line-col-to-point-map
+ (cons start-line start-character?))
+ :end (ht-get line-col-to-point-map
+ (cons end-line end-character?))
+ :kind kind?))
+ it)
+ (seq-filter (lambda (folding-range)
+ (< (lsp--folding-range-beg folding-range)
+ (lsp--folding-range-end folding-range)))
+ it)
+ (seq-into it 'list)
+ (delete-dups it))))))
+ (cdr lsp--cached-folding-ranges))
+
+(defun lsp--get-nested-folding-ranges ()
+ "Get a list of nested folding ranges for the current buffer."
+ (-let [(tick . _) lsp--cached-folding-ranges]
+ (if (and (eq tick (buffer-chars-modified-tick))
+ lsp--cached-nested-folding-ranges)
+ lsp--cached-nested-folding-ranges
+ (setq lsp--cached-nested-folding-ranges
+ (lsp--folding-range-build-trees (lsp--get-folding-ranges))))))
+
+(defun lsp--folding-range-build-trees (ranges)
+ (setq ranges (seq-sort #'lsp--range-before-p ranges))
+ (let* ((dummy-node (make-lsp--folding-range
+ :beg most-negative-fixnum
+ :end most-positive-fixnum))
+ (stack (list dummy-node)))
+ (dolist (range ranges)
+ (while (not (lsp--range-inside-p range (car stack)))
+ (pop stack))
+ (push range (lsp--folding-range-children (car stack)))
+ (push range stack))
+ (lsp--folding-range-children dummy-node)))
+
+(defun lsp--range-inside-p (r1 r2)
+ "Return non-nil if folding range R1 lies inside R2"
+ (and (>= (lsp--folding-range-beg r1) (lsp--folding-range-beg r2))
+ (<= (lsp--folding-range-end r1) (lsp--folding-range-end r2))))
+
+(defun lsp--range-before-p (r1 r2)
+ "Return non-nil if folding range R1 ends before R2"
+ ;; Ensure r1 comes before r2
+ (or (< (lsp--folding-range-beg r1)
+ (lsp--folding-range-beg r2))
+ ;; If beg(r1) == beg(r2) make sure r2 ends first
+ (and (= (lsp--folding-range-beg r1)
+ (lsp--folding-range-beg r2))
+ (< (lsp--folding-range-end r2)
+ (lsp--folding-range-end r1)))))
+
+(defun lsp--point-inside-range-p (point range)
+ "Return non-nil if POINT lies inside folding range RANGE."
+ (and (>= point (lsp--folding-range-beg range))
+ (<= point (lsp--folding-range-end range))))
+
+(cl-defun lsp--get-current-innermost-folding-range (&optional (point (point)))
+ "Return the innermost folding range POINT lies in."
+ (seq-reduce (lambda (innermost-range curr-range)
+ (if (and (lsp--point-inside-range-p point curr-range)
+ (or (null innermost-range)
+ (lsp--range-inside-p curr-range innermost-range)))
+ curr-range
+ innermost-range))
+ (lsp--get-folding-ranges)
+ nil))
+
+(cl-defun lsp--get-current-outermost-folding-range (&optional (point (point)))
+ "Return the outermost folding range POINT lies in."
+ (cdr (seq-reduce (-lambda ((best-pair &as outermost-width . _) curr-range)
+ (let ((curr-width (lsp--folding-range-width curr-range)))
+ (if (and (lsp--point-inside-range-p point curr-range)
+ (or (null best-pair)
+ (> curr-width outermost-width)))
+ (cons curr-width curr-range)
+ best-pair)))
+ (lsp--get-folding-ranges)
+ nil)))
+
+(defun lsp--folding-range-at-point-bounds ()
+ (if (and (or (lsp--capability :foldingRangeProvider)
+ (lsp--registered-capability "textDocument/foldingRange"))
+ lsp-enable-folding)
+ (if-let ((range (lsp--get-current-innermost-folding-range)))
+ (cons (lsp--folding-range-beg range)
+ (lsp--folding-range-end range)))
+ nil))
+(put 'lsp--folding-range 'bounds-of-thing-at-point
+ #'lsp--folding-range-at-point-bounds)
+
+(defun lsp--get-nearest-folding-range (&optional backward)
+ (let ((point (point))
+ (found nil))
+ (while (not
+ (or found
+ (if backward
+ (<= point (point-min))
+ (>= point (point-max)))))
+ (if backward (cl-decf point) (cl-incf point))
+ (setq found (lsp--get-current-innermost-folding-range point)))
+ found))
+
+(defun lsp--folding-range-at-point-forward-op (n)
+ (when (and (or (lsp--capability :foldingRangeProvider)
+ (lsp--registered-capability "textDocument/foldingRange"))
+ lsp-enable-folding
+ (not (zerop n)))
+ (cl-block break
+ (dotimes (_ (abs n))
+ (if-let ((range (lsp--get-nearest-folding-range (< n 0))))
+ (goto-char (if (< n 0)
+ (lsp--folding-range-beg range)
+ (lsp--folding-range-end range)))
+ (cl-return-from break))))))
+(put 'lsp--folding-range 'forward-op
+ #'lsp--folding-range-at-point-forward-op)
+
+(defun lsp--folding-range-at-point-beginning-op ()
+ (goto-char (car (lsp--folding-range-at-point-bounds))))
+(put 'lsp--folding-range 'beginning-op
+ #'lsp--folding-range-at-point-beginning-op)
+
+(defun lsp--folding-range-at-point-end-op ()
+ (goto-char (cdr (lsp--folding-range-at-point-bounds))))
+(put 'lsp--folding-range 'end-op
+ #'lsp--folding-range-at-point-end-op)
+
+(defun lsp--range-at-point-bounds ()
+ (or (lsp--folding-range-at-point-bounds)
+ (when-let ((range (and
+ (lsp--capability :hoverProvider)
+ (->> (lsp--text-document-position-params)
+ (lsp-request "textDocument/hover")
+ (lsp:hover-range?)))))
+ (lsp--range-to-region range))))
+
+;; A more general purpose "thing", useful for applications like focus.el
+(put 'lsp--range 'bounds-of-thing-at-point
+ #'lsp--range-at-point-bounds)
+
+
+;; toggles
+
+(defun lsp-toggle-trace-io ()
+ "Toggle client-server protocol logging."
+ (interactive)
+ (setq lsp-print-io (not lsp-print-io))
+ (lsp--info "Server logging %s." (if lsp-print-io "enabled" "disabled")))
+
+(defun lsp-toggle-signature-auto-activate ()
+ "Toggle signature auto activate."
+ (interactive)
+ (setq lsp-signature-auto-activate
+ (unless lsp-signature-auto-activate '(:on-trigger-char)))
+ (lsp--info "Signature autoactivate %s." (if lsp-signature-auto-activate "enabled" "disabled"))
+ (lsp--update-signature-help-hook))
+
+(defun lsp-toggle-on-type-formatting ()
+ "Toggle on type formatting."
+ (interactive)
+ (setq lsp-enable-on-type-formatting (not lsp-enable-on-type-formatting))
+ (lsp--info "On type formatting is %s." (if lsp-enable-on-type-formatting "enabled" "disabled"))
+ (lsp--update-on-type-formatting-hook))
+
+(defun lsp-toggle-symbol-highlight ()
+ "Toggle symbol highlighting."
+ (interactive)
+ (setq lsp-enable-symbol-highlighting (not lsp-enable-symbol-highlighting))
+
+ (cond
+ ((and lsp-enable-symbol-highlighting
+ (lsp-feature? "textDocument/documentHighlight"))
+ (add-hook 'lsp-on-idle-hook #'lsp--document-highlight nil t)
+ (lsp--info "Symbol highlighting enabled in current buffer."))
+ ((not lsp-enable-symbol-highlighting)
+ (remove-hook 'lsp-on-idle-hook #'lsp--document-highlight t)
+ (lsp--remove-overlays 'lsp-highlight)
+ (lsp--info "Symbol highlighting disabled in current buffer."))))
+
+
+;; keybindings
+(defvar lsp--binding-descriptions nil
+ "List of key binding/short description pair.")
+
+(defmacro lsp-define-conditional-key (keymap key def desc cond &rest bindings)
+ "In KEYMAP, define key sequence KEY as DEF conditionally.
+This is like `define-key', except the definition disappears
+whenever COND evaluates to nil.
+DESC is the short-description for the binding.
+BINDINGS is a list of (key def desc cond)."
+ (declare (indent defun)
+ (debug (form form form form form &rest sexp)))
+ (->> (cl-list* key def desc cond bindings)
+ (-partition 4)
+ (-mapcat (-lambda ((key def desc cond))
+ `((define-key ,keymap ,key
+ '(menu-item
+ ,(format "maybe-%s" def)
+ ,def
+ :filter
+ (lambda (item)
+ (when (with-current-buffer (or (when (buffer-live-p lsp--describe-buffer)
+ lsp--describe-buffer)
+ (current-buffer))
+ ,cond)
+ item))))
+ (when (stringp ,key)
+ (setq lsp--binding-descriptions
+ (nconc lsp--binding-descriptions '(,key ,desc)))))))
+ macroexp-progn))
+
+(defvar lsp--describe-buffer nil)
+
+(defun lsp-describe-buffer-bindings-advice (fn buffer &optional prefix menus)
+ (let ((lsp--describe-buffer buffer))
+ (funcall fn buffer prefix menus)))
+
+(advice-add 'describe-buffer-bindings
+ :around
+ #'lsp-describe-buffer-bindings-advice)
+
+(defun lsp--prepend-prefix (mappings)
+ (->> mappings
+ (-partition 2)
+ (-mapcat (-lambda ((key description))
+ (list (concat lsp-keymap-prefix " " key)
+ description)))))
+
+(defvar lsp-command-map
+ (-doto (make-sparse-keymap)
+ (lsp-define-conditional-key
+ ;; workspaces
+ "wD" lsp-disconnect "disconnect" (lsp-workspaces)
+ "wd" lsp-describe-session "describe session" t
+ "wq" lsp-workspace-shutdown "shutdown server" (lsp-workspaces)
+ "wr" lsp-workspace-restart "restart server" (lsp-workspaces)
+ "ws" lsp "start server" t
+
+ ;; formatting
+ "==" lsp-format-buffer "format buffer" (or (lsp-feature? "textDocument/rangeFormatting")
+ (lsp-feature? "textDocument/formatting"))
+ "=r" lsp-format-region "format region" (lsp-feature? "textDocument/rangeFormatting")
+
+ ;; folders
+ "Fa" lsp-workspace-folders-add "add folder" t
+ "Fb" lsp-workspace-blacklist-remove "un-blacklist folder" t
+ "Fr" lsp-workspace-folders-remove "remove folder" t
+
+ ;; toggles
+ "TD" lsp-modeline-diagnostics-mode "toggle modeline diagnostics" (lsp-feature?
+ "textDocument/publishDiagnostics")
+ "TL" lsp-toggle-trace-io "toggle log io" t
+ "TS" lsp-ui-sideline-mode "toggle sideline" (featurep 'lsp-ui-sideline)
+ "TT" lsp-treemacs-sync-mode "toggle treemacs integration" (featurep 'lsp-treemacs)
+ "Ta" lsp-modeline-code-actions-mode "toggle modeline code actions" (lsp-feature?
+ "textDocument/codeAction")
+ "Tb" lsp-headerline-breadcrumb-mode "toggle breadcrumb" (lsp-feature?
+ "textDocument/documentSymbol")
+ "Td" lsp-ui-doc-mode "toggle documentation popup" (featurep 'lsp-ui-doc)
+ "Tf" lsp-toggle-on-type-formatting "toggle on type formatting" (lsp-feature?
+ "textDocument/onTypeFormatting")
+ "Th" lsp-toggle-symbol-highlight "toggle highlighting" (lsp-feature? "textDocument/documentHighlight")
+ "Tl" lsp-lens-mode "toggle lenses" (lsp-feature? "textDocument/codeLens")
+ "Ts" lsp-toggle-signature-auto-activate "toggle signature" (lsp-feature? "textDocument/signatureHelp")
+
+ ;; goto
+ "ga" xref-find-apropos "find symbol in workspace" (lsp-feature? "workspace/symbol")
+ "gd" lsp-find-declaration "find declarations" (lsp-feature? "textDocument/declaration")
+ "ge" lsp-treemacs-errors-list "show errors" (fboundp 'lsp-treemacs-errors-list)
+ "gg" lsp-find-definition "find definitions" (lsp-feature? "textDocument/definition")
+ "gh" lsp-treemacs-call-hierarchy "call hierarchy" (and (lsp-feature? "callHierarchy/incomingCalls")
+ (fboundp 'lsp-treemacs-call-hierarchy))
+ "gi" lsp-find-implementation "find implementations" (lsp-feature? "textDocument/implementation")
+ "gr" lsp-find-references "find references" (lsp-feature? "textDocument/references")
+ "gt" lsp-find-type-definition "find type definition" (lsp-feature? "textDocument/typeDefinition")
+
+ ;; help
+ "hg" lsp-ui-doc-glance "glance symbol" (and (featurep 'lsp-ui-doc)
+ (lsp-feature? "textDocument/hover"))
+ "hh" lsp-describe-thing-at-point "describe symbol at point" (lsp-feature? "textDocument/hover")
+ "hs" lsp-signature-activate "signature help" (lsp-feature? "textDocument/signatureHelp")
+
+ ;; refactoring
+ "ro" lsp-organize-imports "organize imports" (lsp-feature? "textDocument/codeAction")
+ "rr" lsp-rename "rename" (lsp-feature? "textDocument/rename")
+
+ ;; actions
+ "aa" lsp-execute-code-action "code actions" (lsp-feature? "textDocument/codeAction")
+ "ah" lsp-document-highlight "highlight symbol" (lsp-feature? "textDocument/documentHighlight")
+ "al" lsp-avy-lens "lens" (and (bound-and-true-p lsp-lens-mode) (featurep 'avy))
+
+ ;; peeks
+ "Gg" lsp-ui-peek-find-definitions "peek definitions" (and (lsp-feature? "textDocument/definition")
+ (fboundp 'lsp-ui-peek-find-definitions))
+ "Gi" lsp-ui-peek-find-implementation "peek implementations" (and
+ (fboundp 'lsp-ui-peek-find-implementation)
+ (lsp-feature? "textDocument/implementation"))
+ "Gr" lsp-ui-peek-find-references "peek references" (and (fboundp 'lsp-ui-peek-find-references)
+ (lsp-feature? "textDocument/references"))
+ "Gs" lsp-ui-peek-find-workspace-symbol "peek workspace symbol" (and (fboundp
+ 'lsp-ui-peek-find-workspace-symbol)
+ (lsp-feature? "workspace/symbol")))))
+
+
+;; which-key integration
+
+(declare-function which-key-add-major-mode-key-based-replacements "ext:which-key")
+(declare-function which-key-add-key-based-replacements "ext:which-key")
+
+(defun lsp-enable-which-key-integration (&optional all-modes)
+ "Adds descriptions for `lsp-mode-map' to `which-key-mode' for the current
+active `major-mode', or for all major modes when ALL-MODES is t."
+ (cl-flet ((which-key-fn (if all-modes
+ 'which-key-add-key-based-replacements
+ (apply-partially 'which-key-add-major-mode-key-based-replacements major-mode))))
+ (apply
+ #'which-key-fn
+ (lsp--prepend-prefix
+ (cl-list*
+ "" "lsp"
+ "w" "workspaces"
+ "F" "folders"
+ "=" "formatting"
+ "T" "toggle"
+ "g" "goto"
+ "h" "help"
+ "r" "refactor"
+ "a" "code actions"
+ "G" "peek"
+ lsp--binding-descriptions)))))
+
+
+;; Globbing syntax
+
+;; We port VSCode's glob-to-regexp code
+;; (https://github.com/Microsoft/vscode/blob/466da1c9013c624140f6d1473b23a870abc82d44/src/vs/base/common/glob.ts)
+;; since the LSP globbing syntax seems to be the same as that of
+;; VSCode.
+
+(defconst lsp-globstar "**"
+ "Globstar pattern.")
+
+(defconst lsp-glob-split ?/
+ "The character by which we split path components in a glob
+pattern.")
+
+(defconst lsp-path-regexp "[/\\\\]"
+ "Forward or backslash to be used as a path separator in
+computed regexps.")
+
+(defconst lsp-non-path-regexp "[^/\\\\]"
+ "A regexp matching anything other than a slash.")
+
+(defconst lsp-globstar-regexp
+ (format "\\(?:%s\\|%s+%s\\|%s%s+\\)*?"
+ lsp-path-regexp
+ lsp-non-path-regexp lsp-path-regexp
+ lsp-path-regexp lsp-non-path-regexp)
+ "Globstar in regexp form.")
+
+(defun lsp-split-glob-pattern (pattern split-char)
+ "Split PATTERN at SPLIT-CHAR while respecting braces and brackets."
+ (when pattern
+ (let ((segments nil)
+ (in-braces nil)
+ (in-brackets nil)
+ (current-segment ""))
+ (dolist (char (string-to-list pattern))
+ (cl-block 'exit-point
+ (if (eq char split-char)
+ (when (and (null in-braces)
+ (null in-brackets))
+ (push current-segment segments)
+ (setq current-segment "")
+ (cl-return-from 'exit-point))
+ (pcase char
+ (?{
+ (setq in-braces t))
+ (?}
+ (setq in-braces nil))
+ (?\[
+ (setq in-brackets t))
+ (?\]
+ (setq in-brackets nil))))
+ (setq current-segment (concat current-segment
+ (char-to-string char)))))
+ (unless (string-empty-p current-segment)
+ (push current-segment segments))
+ (nreverse segments))))
+
+(defun lsp--glob-to-regexp (pattern)
+ "Helper function to convert a PATTERN from LSP's glob syntax to
+an Elisp regexp."
+ (if (string-empty-p pattern)
+ ""
+ (let ((current-regexp "")
+ (glob-segments (lsp-split-glob-pattern pattern lsp-glob-split)))
+ (if (-all? (lambda (segment) (eq segment lsp-globstar))
+ glob-segments)
+ ".*"
+ (let ((prev-segment-was-globstar nil))
+ (seq-do-indexed
+ (lambda (segment index)
+ (if (string-equal segment lsp-globstar)
+ (unless prev-segment-was-globstar
+ (setq current-regexp (concat current-regexp
+ lsp-globstar-regexp))
+ (setq prev-segment-was-globstar t))
+ (let ((in-braces nil)
+ (brace-val "")
+ (in-brackets nil)
+ (bracket-val ""))
+ (dolist (char (string-to-list segment))
+ (cond
+ ((and (not (char-equal char ?\}))
+ in-braces)
+ (setq brace-val (concat brace-val
+ (char-to-string char))))
+ ((and in-brackets
+ (or (not (char-equal char ?\]))
+ (string-empty-p bracket-val)))
+ (let ((curr (cond
+ ((char-equal char ?-)
+ "-")
+ ;; NOTE: ?\^ and ?^ are different characters
+ ((and (memq char '(?^ ?!))
+ (string-empty-p bracket-val))
+ "^")
+ ((char-equal char lsp-glob-split)
+ "")
+ (t
+ (regexp-quote (char-to-string char))))))
+ (setq bracket-val (concat bracket-val curr))))
+ (t
+ (cl-case char
+ (?{
+ (setq in-braces t))
+ (?\[
+ (setq in-brackets t))
+ (?}
+ (let* ((choices (lsp-split-glob-pattern brace-val ?\,))
+ (brace-regexp (concat "\\(?:"
+ (mapconcat #'lsp--glob-to-regexp choices "\\|")
+ "\\)")))
+ (setq current-regexp (concat current-regexp
+ brace-regexp))
+ (setq in-braces nil)
+ (setq brace-val "")))
+ (?\]
+ (setq current-regexp
+ (concat current-regexp
+ "[" bracket-val "]"))
+ (setq in-brackets nil)
+ (setq bracket-val ""))
+ (??
+ (setq current-regexp
+ (concat current-regexp
+ lsp-non-path-regexp)))
+ (?*
+ (setq current-regexp
+ (concat current-regexp
+ lsp-non-path-regexp "*?")))
+ (t
+ (setq current-regexp
+ (concat current-regexp
+ (regexp-quote (char-to-string char)))))))))
+ (when (and (< index (1- (length glob-segments)))
+ (or (not (string-equal (nth (1+ index) glob-segments)
+ lsp-globstar))
+ (< (+ index 2)
+ (length glob-segments))))
+ (setq current-regexp
+ (concat current-regexp
+ lsp-path-regexp)))
+ (setq prev-segment-was-globstar nil))))
+ glob-segments)
+ current-regexp)))))
+
+;; See https://github.com/emacs-lsp/lsp-mode/issues/2365
+(defun lsp-glob-unbrace-at-top-level (glob-pattern)
+ "If GLOB-PATTERN does not start with a brace, return a singleton list containing GLOB-PATTERN.
+
+If GLOB-PATTERN does start with a brace, return a list of the
+comma-separated globs within the top-level braces."
+ (if (not (string-prefix-p "{" glob-pattern))
+ (list glob-pattern)
+ (lsp-split-glob-pattern (substring glob-pattern 1 -1) ?\,)))
+
+(defun lsp-glob-convert-to-wrapped-regexp (glob-pattern)
+ "Convert GLOB-PATTERN to a regexp wrapped with the beginning-
+and end-of-string meta-characters."
+ (concat "\\`" (lsp--glob-to-regexp (string-trim glob-pattern)) "\\'"))
+
+(defun lsp-glob-to-regexps (glob-pattern)
+ "Convert a GLOB-PATTERN to a list of Elisp regexps."
+ (let* ((trimmed-pattern (string-trim glob-pattern))
+ (top-level-unbraced-patterns (lsp-glob-unbrace-at-top-level trimmed-pattern)))
+ (seq-map #'lsp-glob-convert-to-wrapped-regexp
+ top-level-unbraced-patterns)))
+
+
+
+(defvar lsp-mode-menu)
+
+(defun lsp-mouse-click (event)
+ (interactive "e")
+ (let* ((ec (event-start event))
+ (choice (x-popup-menu event lsp-mode-menu))
+ (action (lookup-key lsp-mode-menu (apply 'vector choice))))
+
+ (select-window (posn-window ec))
+
+ (unless (and (region-active-p) (eq action 'lsp-execute-code-action))
+ (goto-char (posn-point ec)))
+ (run-with-idle-timer
+ 0.001 nil
+ (lambda ()
+ (cl-labels ((check (value) (not (null value))))
+ (when choice
+ (call-interactively action)))))))
+
+(defvar lsp-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-<down-mouse-1>") #'lsp-find-definition-mouse)
+ (define-key map (kbd "C-<mouse-1>") #'ignore)
+ (define-key map (kbd "<mouse-3>") #'lsp-mouse-click)
+ (define-key map (kbd "C-S-SPC") #'lsp-signature-activate)
+ (when lsp-keymap-prefix
+ (define-key map (kbd lsp-keymap-prefix) lsp-command-map))
+ map)
+ "Keymap for `lsp-mode'.")
+
+(define-minor-mode lsp-mode ""
+ :keymap lsp-mode-map
+ :lighter
+ (" LSP["
+ (lsp--buffer-workspaces
+ (:eval (mapconcat #'lsp--workspace-print lsp--buffer-workspaces "]["))
+ (:propertize "Disconnected" face warning))
+ "]")
+ :group 'lsp-mode)
+
+(defvar lsp-mode-menu
+ (easy-menu-create-menu
+ nil
+ `(["Go to definition" lsp-find-definition
+ :active (lsp-feature? "textDocument/definition")]
+ ["Find references" lsp-find-references
+ :active (lsp-feature? "textDocument/references")]
+ ["Find implementations" lsp-find-implementation
+ :active (lsp-feature? "textDocument/implementation")]
+ ["Find declarations" lsp-find-declaration
+ :active (lsp-feature? "textDocument/declaration")]
+ ["Go to type declaration" lsp-find-type-definition
+ :active (lsp-feature? "textDocument/typeDefinition")]
+ "--"
+ ["Describe" lsp-describe-thing-at-point]
+ ["Code action" lsp-execute-code-action]
+ ["Format" lsp-format-buffer]
+ ["Highlight references" lsp-document-highlight]
+ ["Type Hierarchy" lsp-java-type-hierarchy
+ :visible (lsp-can-execute-command? "java.navigate.resolveTypeHierarchy")]
+ ["Type Hierarchy" lsp-treemacs-type-hierarchy
+ :visible (and (not (lsp-can-execute-command? "java.navigate.resolveTypeHierarchy"))
+ (functionp 'lsp-treemacs-type-hierarchy)
+ (lsp-feature? "textDocument/typeHierarchy"))]
+ ["Call Hierarchy" lsp-treemacs-call-hierarchy
+ :visible (and (functionp 'lsp-treemacs-call-hierarchy)
+ (lsp-feature? "textDocument/callHierarchy"))]
+ ["Rename" lsp-rename
+ :active (lsp-feature? "textDocument/rename")]
+ "--"
+ ("Session"
+ ["View logs" lsp-workspace-show-log]
+ ["Describe" lsp-describe-session]
+ ["Shutdown" lsp-shutdown-workspace]
+ ["Restart" lsp-restart-workspace])
+ ("Workspace Folders"
+ ["Add" lsp-workspace-folders-add]
+ ["Remove" lsp-workspace-folders-remove]
+ ["Open" lsp-workspace-folders-open])
+ ("Toggle features"
+ ["Lenses" lsp-lens-mode]
+ ["Headerline breadcrumb" lsp-headerline-breadcrumb-mode]
+ ["Modeline code actions" lsp-modeline-code-actions-mode]
+ ["Modeline diagnostics" lsp-modeline-diagnostics-mode])
+ "---"
+ ("Debug"
+ :active (bound-and-true-p dap-ui-mode)
+ :filter ,(lambda (_)
+ (and (boundp 'dap-ui-menu-items)
+ (nthcdr 3 dap-ui-menu-items))))))
+ "Menu for lsp-mode.")
+
+(defalias 'make-lsp-client 'make-lsp--client)
+
+(cl-defstruct lsp--registered-capability
+ (id "")
+ (method " ")
+ (options nil))
+
+;; A ‘lsp--workspace’ object represents exactly one language server process.
+(cl-defstruct lsp--workspace
+ ;; the `ewoc' object for displaying I/O to and from the server
+ (ewoc nil)
+
+ ;; ‘server-capabilities’ is a hash table of the language server capabilities.
+ ;; It is the hash table representation of a LSP ServerCapabilities structure;
+ ;; cf. https://microsoft.github.io/language-server-protocol/specification#initialize.
+ (server-capabilities nil)
+
+ ;; ‘registered-server-capabilities’ is a list of hash tables that represent
+ ;; dynamically-registered Registration objects. See
+ ;; https://microsoft.github.io/language-server-protocol/specification#client_registerCapability.
+ (registered-server-capabilities nil)
+
+ ;; ‘root’ is a directory name or a directory file name for the workspace
+ ;; root. ‘lsp-mode’ passes this directory to the ‘initialize’ method of the
+ ;; language server; see
+ ;; https://microsoft.github.io/language-server-protocol/specification#initialize.
+ (root nil)
+
+ ;; ‘client’ is the ‘lsp--client’ object associated with this workspace.
+ (client nil)
+
+ ;; ‘host-root’ contains the host root info as derived from `file-remote-p'. It
+ ;; used to derive the file path in `lsp--uri-to-path' when using tramp
+ ;; connection.
+ (host-root nil)
+
+ ;; ‘proc’ is a process object; it may represent a regular process, a pipe, or
+ ;; a network connection. ‘lsp-mode’ communicates with ‘proc’ using the
+ ;; language server protocol. ‘proc’ corresponds to the COMMUNICATION-PROCESS
+ ;; element of the return value of the client’s ‘get-root’ field, which see.
+ (proc nil)
+
+ ;; ‘proc’ is a process object; it must represent a regular process, not a
+ ;; pipe or network process. It represents the actual server process that
+ ;; corresponds to this workspace. ‘cmd-proc’ corresponds to the
+ ;; COMMAND-PROCESS element of the return value of the client’s ‘get-root’
+ ;; field, which see.
+ (cmd-proc nil)
+
+ ;; ‘buffers’ is a list of buffers associated with this workspace.
+ (buffers nil)
+
+ ;; if semantic tokens is enabled, `semantic-tokens-faces' contains
+ ;; one face (or nil) for each token type supported by the language server.
+ (semantic-tokens-faces nil)
+
+ ;; If semantic highlighting is enabled, `semantic-tokens-modifier-faces'
+ ;; contains one face (or nil) for each modifier type supported by the language
+ ;; server
+ (semantic-tokens-modifier-faces nil)
+
+ ;; Extra client capabilities provided by third-party packages using
+ ;; `lsp-register-client-capabilities'. It's value is an alist of (PACKAGE-NAME
+ ;; . CAPS), where PACKAGE-NAME is a symbol of the third-party package name,
+ ;; and CAPS is either a plist of the client capabilities, or a function that
+ ;; takes no argument and returns a plist of the client capabilities or nil.")
+ (extra-client-capabilities nil)
+
+ ;; Workspace status
+ (status nil)
+
+ ;; ‘metadata’ is a generic storage for workspace specific data. It is
+ ;; accessed via `lsp-workspace-set-metadata' and `lsp-workspace-set-metadata'
+ (metadata (make-hash-table :test 'equal))
+
+ ;; contains all the file notification watches that have been created for the
+ ;; current workspace in format filePath->file notification handle.
+ (watches (make-hash-table :test 'equal))
+
+ ;; list of workspace folders
+ (workspace-folders nil)
+
+ ;; ‘last-id’ the last request id for the current workspace.
+ (last-id 0)
+
+ ;; ‘status-string’ allows extensions to specify custom status string based on
+ ;; the Language Server specific messages.
+ (status-string nil)
+
+ ;; ‘shutdown-action’ flag used to mark that workspace should not be restarted (e.g. it
+ ;; was stopped).
+ shutdown-action
+
+ ;; ‘diagnostics’ a hashmap with workspace diagnostics.
+ (diagnostics (make-hash-table :test 'equal))
+
+ ;; contains all the workDone progress tokens that have been created
+ ;; for the current workspace.
+ (work-done-tokens (make-hash-table :test 'equal)))
+
+
+(cl-defstruct lsp-session
+ ;; contains the folders that are part of the current session
+ folders
+ ;; contains the folders that must not be imported in the current workspace.
+ folders-blacklist
+ ;; contains the list of folders that must be imported in a project in case of
+ ;; multi root LSP server.
+ (server-id->folders (make-hash-table :test 'equal))
+ ;; folder to list of the servers that are associated with the folder.
+ (folder->servers (make-hash-table :test 'equal))
+ ;; ‘metadata’ is a generic storage for workspace specific data. It is
+ ;; accessed via `lsp-workspace-set-metadata' and `lsp-workspace-set-metadata'
+ (metadata (make-hash-table :test 'equal)))
+
+(defun lsp-workspace-status (status-string &optional workspace)
+ "Set current workspace status to STATUS-STRING.
+If WORKSPACE is not specified defaults to lsp--cur-workspace."
+ (let ((status-string (when status-string (replace-regexp-in-string "%" "%%" status-string))))
+ (setf (lsp--workspace-status-string (or workspace lsp--cur-workspace)) status-string)))
+
+(defun lsp-session-set-metadata (key value &optional _workspace)
+ "Associate KEY with VALUE in the WORKSPACE metadata.
+If WORKSPACE is not provided current workspace will be used."
+ (puthash key value (lsp-session-metadata (lsp-session))))
+
+(defalias 'lsp-workspace-set-metadata 'lsp-session-set-metadata)
+
+(defun lsp-session-get-metadata (key &optional _workspace)
+ "Lookup KEY in WORKSPACE metadata.
+If WORKSPACE is not provided current workspace will be used."
+ (gethash key (lsp-session-metadata (lsp-session))))
+
+(defalias 'lsp-workspace-get-metadata 'lsp-session-get-metadata)
+
+(defun lsp-workspace-set-work-done-token (token value workspace)
+ "Associate TOKEN with VALUE in the WORKSPACE work-done-tokens."
+ (puthash token value (lsp--workspace-work-done-tokens workspace)))
+
+(defun lsp-workspace-get-work-done-token (token workspace)
+ "Lookup TOKEN in the WORKSPACE work-done-tokens."
+ (gethash token (lsp--workspace-work-done-tokens workspace)))
+
+(defun lsp-workspace-rem-work-done-token (token workspace)
+ "Remove TOKEN from the WORKSPACE work-done-tokens."
+ (remhash token (lsp--workspace-work-done-tokens workspace)))
+
+
+(defun lsp--make-notification (method &optional params)
+ "Create notification body for method METHOD and parameters PARAMS."
+ (list :jsonrpc "2.0" :method method :params params))
+
+(defalias 'lsp--make-request 'lsp--make-notification)
+(defalias 'lsp-make-request 'lsp--make-notification)
+
+(defun lsp--make-response (id result)
+ "Create response for REQUEST with RESULT."
+ `(:jsonrpc "2.0" :id ,id :result ,result))
+
+(defun lsp-make-notification (method &optional params)
+ "Create notification body for method METHOD and parameters PARAMS."
+ (lsp--make-notification method params))
+
+(defmacro lsp--json-serialize (params)
+ (if (progn
+ (require 'json)
+ (fboundp 'json-serialize))
+ `(json-serialize ,params
+ :null-object nil
+ :false-object :json-false)
+ `(let ((json-false :json-false))
+ (json-encode ,params))))
+
+(defun lsp--make-message (params)
+ "Create a LSP message from PARAMS, after encoding it to a JSON string."
+ (let ((body (lsp--json-serialize params)))
+ (concat "Content-Length: "
+ (number-to-string (1+ (string-bytes body)))
+ "\r\n\r\n"
+ body
+ "\n")))
+
+(cl-defstruct lsp--log-entry timestamp process-time type method id body)
+
+(defun lsp--make-log-entry (method id body type &optional process-time)
+ "Create an outgoing log object from BODY with method METHOD and id ID.
+If ID is non-nil, then the body is assumed to be a notification.
+TYPE can either be 'incoming or 'outgoing"
+ (cl-assert (memq type '(incoming-req outgoing-req incoming-notif
+ outgoing-notif incoming-resp
+ outgoing-resp)))
+ (make-lsp--log-entry
+ :timestamp (format-time-string "%I:%M:%S %p")
+ :process-time process-time
+ :method method
+ :id id
+ :type type
+ :body body))
+
+(defun lsp--log-entry-pp (entry)
+ (cl-assert (lsp--log-entry-p entry))
+ (pcase-let (((cl-struct lsp--log-entry timestamp method id type process-time
+ body)
+ entry)
+ (json-false :json-false)
+ (json-encoding-pretty-print t)
+ (str nil))
+ (setq str
+ (concat (format "[Trace - %s] " timestamp)
+ (pcase type
+ ('incoming-req (format "Received request '%s - (%s)." method id))
+ ('outgoing-req (format "Sending request '%s - (%s)'." method id))
+
+ ('incoming-notif (format "Received notification '%s'." method))
+ ('outgoing-notif (format "Sending notification '%s'." method))
+
+ ('incoming-resp (format "Received response '%s - (%s)' in %dms."
+ method id process-time))
+ ('outgoing-resp
+ (format
+ "Sending response '%s - (%s)'. Processing request took %dms"
+ method id process-time)))
+ "\n"
+ (if (memq type '(incoming-resp ougoing-resp))
+ "Result: "
+ "Params: ")
+ (json-encode body)
+ "\n\n\n"))
+ (setq str (propertize str 'mouse-face 'highlight 'read-only t))
+ (insert str)))
+
+(defvar-local lsp--log-io-ewoc nil)
+
+(defun lsp--get-create-io-ewoc (workspace)
+ (if (and (lsp--workspace-ewoc workspace)
+ (buffer-live-p (ewoc-buffer (lsp--workspace-ewoc workspace))))
+ (lsp--workspace-ewoc workspace)
+ (with-current-buffer (lsp--get-log-buffer-create workspace)
+ (unless (eq 'lsp-log-io-mode major-mode) (lsp-log-io-mode))
+ (setq-local window-point-insertion-type t)
+ (setq lsp--log-io-ewoc (ewoc-create #'lsp--log-entry-pp nil nil t))
+ (setf (lsp--workspace-ewoc workspace) lsp--log-io-ewoc))
+ (lsp--workspace-ewoc workspace)))
+
+(defun lsp--ewoc-count (ewoc)
+ (let* ((count 0)
+ (count-fn (lambda (_) (setq count (1+ count)))))
+ (ewoc-map count-fn ewoc)
+ count))
+
+(defun lsp--log-entry-new (entry workspace)
+ (let* ((ewoc (lsp--get-create-io-ewoc workspace))
+ (count (and (not (eq lsp-io-messages-max t)) (lsp--ewoc-count ewoc)))
+ (node (if (or (eq lsp-io-messages-max t)
+ (>= lsp-io-messages-max count))
+ nil
+ (ewoc-nth ewoc (1- lsp-io-messages-max))))
+ (prev nil)
+ (inhibit-read-only t))
+ (while node
+ (setq prev (ewoc-prev ewoc node))
+ (ewoc-delete ewoc node)
+ (setq node prev))
+ (ewoc-enter-last ewoc entry)))
+
+(defun lsp--send-notification (body)
+ "Send BODY as a notification to the language server."
+ (lsp-foreach-workspace
+ (when lsp-print-io
+ (lsp--log-entry-new (lsp--make-log-entry
+ (plist-get body :method)
+ nil (plist-get body :params) 'outgoing-notif)
+ lsp--cur-workspace))
+ (lsp--send-no-wait (lsp--make-message body)
+ (lsp--workspace-proc lsp--cur-workspace))))
+
+(defalias 'lsp-send-notification 'lsp--send-notification)
+
+(defun lsp-notify (method params)
+ "Send notification METHOD with PARAMS."
+ (lsp--send-notification (lsp--make-notification method params)))
+
+(defun lsp--cur-workspace-check ()
+ "Check whether buffer lsp workspace(s) are set."
+ (cl-assert (lsp-workspaces) nil
+ "No language server(s) is associated with this buffer."))
+
+(defun lsp--send-request (body &optional no-wait no-merge)
+ "Send BODY as a request to the language server, get the response.
+If NO-WAIT is non-nil, don't synchronously wait for a response.
+If NO-MERGE is non-nil, don't merge the results but return an
+alist mapping workspace->result."
+ (lsp-request (plist-get body :method)
+ (plist-get body :params)
+ :no-wait no-wait
+ :no-merge no-merge))
+
+(defalias 'lsp-send-request 'lsp--send-request
+ "Send BODY as a request to the language server and return the response
+synchronously.
+\n(fn BODY)")
+
+(cl-defun lsp-request (method params &key no-wait no-merge)
+ "Send request METHOD with PARAMS.
+If NO-MERGE is non-nil, don't merge the results but return alist workspace->result.
+If NO-WAIT is non-nil send the request as notification."
+ (if no-wait
+ (lsp-notify method params)
+ (let* ((send-time (time-to-seconds (current-time)))
+ ;; max time by which we must get a response
+ (expected-time (+ send-time lsp-response-timeout))
+ resp-result resp-error done?)
+ (unwind-protect
+ (progn
+ (lsp-request-async method params
+ (lambda (res) (setf resp-result (or res :finished)) (throw 'lsp-done '_))
+ :error-handler (lambda (err) (setf resp-error err) (throw 'lsp-done '_))
+ :no-merge no-merge
+ :mode 'detached
+ :cancel-token :sync-request)
+ (while (not (or resp-error resp-result))
+ (catch 'lsp-done
+ (accept-process-output nil (- expected-time send-time)))
+ (setq send-time (time-to-seconds (current-time)))
+ (when (< expected-time send-time)
+ (error "Timeout while waiting for response. Method: %s" method)))
+ (setq done? t)
+ (cond
+ ((eq resp-result :finished) nil)
+ (resp-result resp-result)
+ ((lsp-json-error? resp-error) (error (lsp:json-error-message resp-error)))
+ ((lsp-json-error? (cl-first resp-error))
+ (error (lsp:json-error-message (cl-first resp-error))))))
+ (unless done?
+ (lsp-cancel-request-by-token :sync-request))))))
+
+(cl-defun lsp-request-while-no-input (method params)
+ "Send request METHOD with PARAMS and waits until there is no input.
+Return same value as `lsp--while-no-input' and respecting `non-essential'."
+ (if non-essential
+ (let* ((send-time (time-to-seconds (current-time)))
+ ;; max time by which we must get a response
+ (expected-time (+ send-time lsp-response-timeout))
+ resp-result resp-error done?)
+ (unwind-protect
+ (progn
+ (lsp-request-async method params
+ (lambda (res) (setf resp-result (or res :finished)) (throw 'lsp-done '_))
+ :error-handler (lambda (err) (setf resp-error err) (throw 'lsp-done '_))
+ :mode 'detached
+ :cancel-token :sync-request)
+ (while (not (or resp-error resp-result (input-pending-p)))
+ (catch 'lsp-done
+ (sit-for (- expected-time send-time)))
+ (setq send-time (time-to-seconds (current-time)))
+ (when (< expected-time send-time)
+ (error "Timeout while waiting for response. Method: %s" method)))
+ (setq done? (or resp-error resp-result))
+ (cond
+ ((eq resp-result :finished) nil)
+ (resp-result resp-result)
+ ((lsp-json-error? resp-error) (error (lsp:json-error-message resp-error)))
+ ((lsp-json-error? (cl-first resp-error))
+ (error (lsp:json-error-message (cl-first resp-error))))))
+ (unless done?
+ (lsp-cancel-request-by-token :sync-request))
+ (when (and (input-pending-p) lsp--throw-on-input)
+ (throw 'input :interrupted))))
+ (lsp-request method params)))
+
+(defvar lsp--cancelable-requests (ht))
+
+(cl-defun lsp-request-async (method params callback
+ &key mode error-handler cancel-handler no-merge cancel-token)
+ "Send METHOD with PARAMS as a request to the language server.
+Call CALLBACK with the response received from the server
+asynchronously.
+MODE determines when the callback will be called depending on the
+condition of the original buffer. It could be:
+- `detached' which means that the callback will be executed no
+matter what has happened to the buffer.
+- `alive' - the callback will be executed only if the buffer from
+which the call was executed is still alive.
+- `current' the callback will be executed only if the original buffer
+is still selected.
+- `tick' - the callback will be executed only if the buffer was not modified.
+- `unchanged' - the callback will be executed only if the buffer hasn't
+changed and if the buffer is not modified.
+
+ERROR-HANDLER will be called in case the request has failed.
+CANCEL-HANDLER will be called in case the request is being canceled.
+If NO-MERGE is non-nil, don't merge the results but return alist
+workspace->result.
+CANCEL-TOKEN is the token that can be used to cancel request."
+ (lsp--send-request-async `(:jsonrpc "2.0" :method ,method :params ,params)
+ callback mode error-handler cancel-handler no-merge cancel-token))
+
+(defun lsp--create-request-cancel (id workspaces hook buf method cancel-callback)
+ (lambda (&rest _)
+ (unless (and (equal 'post-command-hook hook)
+ (equal (current-buffer) buf))
+ (lsp--request-cleanup-hooks id)
+ (with-lsp-workspaces workspaces
+ (lsp--cancel-request id)
+ (when cancel-callback (funcall cancel-callback)))
+ (lsp-log "Cancelling %s(%s) in hook %s" method id hook))))
+
+(defun lsp--create-async-callback
+ (callback method no-merge workspaces)
+ "Create async handler expecting COUNT results, merge them and call CALLBACK.
+MODE determines when the callback will be called depending on the
+condition of the original buffer. METHOD is the invoked method.
+If NO-MERGE is non-nil, don't merge the results but return alist workspace->result.
+ID is the request id. "
+ (let (results errors)
+ (lambda (result)
+ (push (cons lsp--cur-workspace result)
+ (if (eq result :error) errors results))
+ (when (and (not (eq (length errors) (length workspaces)))
+ (eq (+ (length errors) (length results)) (length workspaces)))
+ (funcall callback
+ (if no-merge
+ results
+ (lsp--merge-results (-map #'cl-rest results) method)))))))
+
+(defun lsp--create-default-error-handler (method)
+ "Default error handler.
+METHOD is the executed method."
+ (lambda (error)
+ (lsp--warn "%s" (or (lsp--error-string error)
+ (format "%s Request has failed" method)))))
+
+(defvar lsp--request-cleanup-hooks (ht))
+
+(defun lsp--request-cleanup-hooks (request-id)
+ (when-let ((cleanup-function (gethash request-id lsp--request-cleanup-hooks)))
+ (funcall cleanup-function)
+ (remhash request-id lsp--request-cleanup-hooks)))
+
+(defun lsp-cancel-request-by-token (cancel-token)
+ "Cancel request using CANCEL-TOKEN."
+ (-when-let ((request-id . workspaces) (gethash cancel-token lsp--cancelable-requests))
+ (with-lsp-workspaces workspaces
+ (lsp--cancel-request request-id))
+ (remhash cancel-token lsp--cancelable-requests)
+ (lsp--request-cleanup-hooks request-id)))
+
+(defun lsp--send-request-async (body callback
+ &optional mode error-callback cancel-callback
+ no-merge cancel-token)
+ "Send BODY as a request to the language server.
+Call CALLBACK with the response received from the server
+asynchronously.
+MODE determines when the callback will be called depending on the
+condition of the original buffer. It could be:
+- `detached' which means that the callback will be executed no
+matter what has happened to the buffer.
+- `alive' - the callback will be executed only if the buffer from
+which the call was executed is still alive.
+- `current' the callback will be executed only if the original buffer
+is still selected.
+- `tick' - the callback will be executed only if the buffer was not modified.
+- `unchanged' - the callback will be executed only if the buffer hasn't
+changed and if the buffer is not modified.
+
+ERROR-CALLBACK will be called in case the request has failed.
+CANCEL-CALLBACK will be called in case the request is being canceled.
+If NO-MERGE is non-nil, don't merge the results but return alist
+workspace->result.
+CANCEL-TOKEN is the token that can be used to cancel request."
+ (when cancel-token
+ (lsp-cancel-request-by-token cancel-token))
+
+ (if-let ((target-workspaces (lsp--find-workspaces-for body)))
+ (let* ((start-time (current-time))
+ (method (plist-get body :method))
+ (id (cl-incf lsp-last-id))
+ ;; calculate what are the (hook . local) pairs which will cancel
+ ;; the request
+ (hooks (pcase mode
+ ('alive '((kill-buffer-hook . t)))
+ ('tick '((kill-buffer-hook . t) (after-change-functions . t)))
+ ('unchanged '((after-change-functions . t) (post-command-hook . nil)))
+ ('current '((post-command-hook . nil)))))
+ (buf (current-buffer))
+ ;; note: lambdas in emacs can be compared but we should make sure
+ ;; that all of the captured arguments are the same - in our case
+ ;; `lsp--create-request-cancel' will return the same lambda when
+ ;; called with the same params.
+ (cleanup-hooks
+ (lambda () (mapc
+ (-lambda ((hook . local))
+ (if local
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (remove-hook hook
+ (lsp--create-request-cancel
+ id target-workspaces hook buf method cancel-callback)
+ t)))
+ (remove-hook hook (lsp--create-request-cancel
+ id target-workspaces hook buf method cancel-callback))))
+ hooks)
+ (remhash cancel-token lsp--cancelable-requests)))
+ (callback (pcase mode
+ ((or 'alive 'tick) (lambda (&rest args)
+ (with-current-buffer buf
+ (apply callback args))))
+ (_ callback)))
+ (callback (lsp--create-async-callback callback
+ method
+ no-merge
+ target-workspaces))
+ (callback (lambda (result)
+ (lsp--request-cleanup-hooks id)
+ (funcall callback result)))
+ (error-callback (lsp--create-async-callback
+ (or error-callback
+ (lsp--create-default-error-handler method))
+ method
+ nil
+ target-workspaces))
+ (error-callback (lambda (error)
+ (funcall callback :error)
+ (lsp--request-cleanup-hooks id)
+ (funcall error-callback error)))
+ (cancel-callback (when cancel-callback
+ (pcase mode
+ ((or 'alive 'tick 'unchanged)
+ (lambda ()
+ (with-current-buffer buf
+ (funcall cancel-callback))))
+ (_ cancel-callback))))
+ (body (plist-put body :id id)))
+
+ ;; cancel request in any of the hooks
+ (mapc (-lambda ((hook . local))
+ (add-hook hook
+ (lsp--create-request-cancel
+ id target-workspaces hook buf method cancel-callback)
+ nil local))
+ hooks)
+ (puthash id cleanup-hooks lsp--request-cleanup-hooks)
+
+ (setq lsp--last-active-workspaces target-workspaces)
+
+ (when cancel-token
+ (puthash cancel-token (cons id target-workspaces) lsp--cancelable-requests))
+
+ (seq-doseq (workspace target-workspaces)
+ (when lsp-log-io
+ (lsp--log-entry-new (lsp--make-log-entry method id
+ (plist-get body :params)
+ 'outgoing-req)
+ workspace))
+ (let ((message (lsp--make-message body)))
+ (puthash id
+ (list callback error-callback method start-time (current-time))
+ (-> workspace
+ (lsp--workspace-client)
+ (lsp--client-response-handlers)))
+ (lsp--send-no-wait message (lsp--workspace-proc workspace))))
+ body)
+ (error "The connected server(s) does not support method %s.
+To find out what capabilities support your server use `M-x lsp-describe-session'
+and expand the capabilities section"
+ (plist-get body :method))))
+
+;; deprecated, use lsp-request-async.
+(defalias 'lsp-send-request-async 'lsp--send-request-async)
+(make-obsolete 'lsp-send-request-async 'lsp-request-async "lsp-mode 7.0.1")
+
+;; Clean up the entire state of lsp mode when Emacs is killed, to get rid of any
+;; pending language servers.
+(add-hook 'kill-emacs-hook #'lsp--global-teardown)
+
+(defun lsp--global-teardown ()
+ "Unload working workspaces."
+ (lsp-foreach-workspace (lsp--shutdown-workspace)))
+
+(defun lsp--shutdown-workspace (&optional restart)
+ "Shut down the language server process for ‘lsp--cur-workspace’."
+ (with-demoted-errors "LSP error: %S"
+ (let ((lsp-response-timeout 0.5))
+ (condition-case _err
+ (lsp-request "shutdown" lsp--empty-ht)
+ (error (lsp--error "Timeout while sending shutdown request"))))
+ (lsp-notify "exit" nil))
+ (setf (lsp--workspace-shutdown-action lsp--cur-workspace) (or (and restart 'restart) 'shutdown))
+ (lsp--uninitialize-workspace))
+
+(defun lsp--uninitialize-workspace ()
+ "Cleanup buffer state.
+When a workspace is shut down, by request or from just
+disappearing, unset all the variables related to it."
+ (let ((proc (lsp--workspace-cmd-proc lsp--cur-workspace))
+ (buffers (lsp--workspace-buffers lsp--cur-workspace)))
+ (when (process-live-p proc)
+ (kill-process proc))
+ (mapc (lambda (buf)
+ (when (lsp-buffer-live-p buf)
+ (lsp-with-current-buffer buf
+ (lsp-managed-mode -1))))
+ buffers)
+ (lsp-diagnostics--workspace-cleanup lsp--cur-workspace)))
+
+(defun lsp--client-capabilities (&optional custom-capabilities)
+ "Return the client capabilities appending CUSTOM-CAPABILITIES."
+ (append
+ `((workspace . ((workspaceEdit . ((documentChanges . t)
+ (resourceOperations . ["create" "rename" "delete"])))
+ (applyEdit . t)
+ (symbol . ((symbolKind . ((valueSet . ,(apply 'vector (number-sequence 1 26)))))))
+ (executeCommand . ((dynamicRegistration . :json-false)))
+ ,@(when lsp-enable-file-watchers '((didChangeWatchedFiles . ((dynamicRegistration . t)))))
+ (workspaceFolders . t)
+ (configuration . t)
+ ,@(when lsp-semantic-tokens-enable '((semanticTokens . ((refreshSupport . t)))))
+ ,@(when lsp-lens-enable '((codeLens . ((refreshSupport . :json-false)))))
+ (fileOperations . ((didCreate . :json-false)
+ (willCreate . :json-false)
+ (didRename . :json-false)
+ (willRename . :json-false)
+ (didDelete . :json-false)
+ (willDelete . :json-false)))))
+ (textDocument . ((declaration . ((linkSupport . t)))
+ (definition . ((linkSupport . t)))
+ (implementation . ((linkSupport . t)))
+ (typeDefinition . ((linkSupport . t)))
+ (synchronization . ((willSave . t) (didSave . t) (willSaveWaitUntil . t)))
+ (documentSymbol . ((symbolKind . ((valueSet . ,(apply 'vector (number-sequence 1 26)))))
+ (hierarchicalDocumentSymbolSupport . t)))
+ (formatting . ((dynamicRegistration . t)))
+ (rangeFormatting . ((dynamicRegistration . t)))
+ ,@(when (and lsp-semantic-tokens-enable
+ (boundp 'lsp-semantic-tokens-capabilities))
+ lsp-semantic-tokens-capabilities)
+ (rename . ((dynamicRegistration . t) (prepareSupport . t)))
+ (codeAction . ((dynamicRegistration . t)
+ (isPreferredSupport . t)
+ (codeActionLiteralSupport . ((codeActionKind . ((valueSet . [""
+ "quickfix"
+ "refactor"
+ "refactor.extract"
+ "refactor.inline"
+ "refactor.rewrite"
+ "source"
+ "source.organizeImports"])))))
+ (resolveSupport . ((properties . ["edit" "command"])))
+ (dataSupport . t)))
+ (completion . ((completionItem . ((snippetSupport . ,(cond
+ ((and lsp-enable-snippet (not (featurep 'yasnippet)) t)
+ (lsp--warn (concat
+ "Yasnippet is not installed, but `lsp-enable-snippet' is set to `t'. "
+ "You must either install yasnippet, or disable snippet support."))
+ :json-false)
+ (lsp-enable-snippet t)
+ (t :json-false)))
+ (documentationFormat . ["markdown" "plaintext"])
+ ;; Remove this after jdtls support resolveSupport
+ (resolveAdditionalTextEditsSupport . t)
+ (insertReplaceSupport . t)
+ (resolveSupport
+ . ((properties . ["documentation"
+ "details"
+ "additionalTextEdits"
+ "command"])))
+ (insertTextModeSupport . ((valueSet . [1 2])))))
+ (contextSupport . t)))
+ (signatureHelp . ((signatureInformation . ((parameterInformation . ((labelOffsetSupport . t)))))))
+ (documentLink . ((dynamicRegistration . t)
+ (tooltipSupport . t)))
+ (hover . ((contentFormat . ["markdown" "plaintext"])))
+ (foldingRange . ,(when lsp-enable-folding
+ `((dynamicRegistration . t)
+ ,@(when lsp-folding-range-limit
+ `((rangeLimit . ,lsp-folding-range-limit)))
+ ,@(when lsp-folding-line-folding-only
+ `((lineFoldingOnly . t))))))
+ (callHierarchy . ((dynamicRegistration . :json-false)))
+ (publishDiagnostics . ((relatedInformation . t)
+ (tagSupport . ((valueSet . [1 2])))
+ (versionSupport . t)))
+ (moniker . nil)
+ (linkedEditingRange . nil)))
+ (window . ((workDoneProgress . t)
+ (showMessage . nil)
+ (showDocument . nil))))
+ custom-capabilities))
+
+(defun lsp-find-roots-for-workspace (workspace session)
+ "Get all roots for the WORKSPACE."
+ (-filter #'identity (ht-map (lambda (folder workspaces)
+ (when (-contains? workspaces workspace)
+ folder))
+ (lsp-session-folder->servers session))))
+
+(defun lsp-session-watches (&optional session)
+ "Get watches created for SESSION."
+ (or (gethash "__watches" (lsp-session-metadata (or session (lsp-session))))
+ (-let [res (make-hash-table :test 'equal)]
+ (puthash "__watches" res (lsp-session-metadata (or session (lsp-session))))
+ res)))
+
+(defun lsp--file-process-event (session root-folder event)
+ "Process file event."
+ (let* ((changed-file (cl-third event))
+ (rel-changed-file (f-relative changed-file root-folder))
+ (event-numeric-kind (alist-get (cl-second event) lsp--file-change-type))
+ (bit-position (1- event-numeric-kind))
+ (watch-bit (ash 1 bit-position)))
+ (->>
+ session
+ lsp-session-folder->servers
+ (gethash root-folder)
+ (seq-do (lambda (workspace)
+ (when (->>
+ workspace
+ lsp--workspace-registered-server-capabilities
+ (-any?
+ (lambda (capability)
+ (and
+ (equal (lsp--registered-capability-method capability)
+ "workspace/didChangeWatchedFiles")
+ (->>
+ capability
+ lsp--registered-capability-options
+ (lsp:did-change-watched-files-registration-options-watchers)
+ (seq-find
+ (-lambda ((&FileSystemWatcher :glob-pattern :kind?))
+ (when (or (null kind?)
+ (> (logand kind? watch-bit) 0))
+ (-let [regexes (lsp-glob-to-regexps glob-pattern)]
+ (-any? (lambda (re)
+ (or (string-match re changed-file)
+ (string-match re rel-changed-file)))
+ regexes))))))))))
+ (with-lsp-workspace workspace
+ (lsp-notify
+ "workspace/didChangeWatchedFiles"
+ `((changes . [((type . ,event-numeric-kind)
+ (uri . ,(lsp--path-to-uri changed-file)))]))))))))))
+
+(lsp-defun lsp--server-register-capability ((&Registration :method :id :register-options?))
+ "Register capability REG."
+ (when (and lsp-enable-file-watchers
+ (equal method "workspace/didChangeWatchedFiles"))
+ (-let* ((created-watches (lsp-session-watches (lsp-session)))
+ (root-folders (cl-set-difference
+ (lsp-find-roots-for-workspace lsp--cur-workspace (lsp-session))
+ (ht-keys created-watches))))
+ ;; create watch for each root folder without such
+ (dolist (folder root-folders)
+ (let* ((watch (make-lsp-watch :root-directory folder))
+ (ignored-things (lsp--get-ignored-regexes-for-workspace-root folder))
+ (ignored-files-regex-list (car ignored-things))
+ (ignored-directories-regex-list (cadr ignored-things)))
+ (puthash folder watch created-watches)
+ (lsp-watch-root-folder (file-truename folder)
+ (-partial #'lsp--file-process-event (lsp-session) folder)
+ ignored-files-regex-list
+ ignored-directories-regex-list
+ watch
+ t)))))
+
+ (push
+ (make-lsp--registered-capability :id id :method method :options register-options?)
+ (lsp--workspace-registered-server-capabilities lsp--cur-workspace)))
+
+(defmacro lsp--with-workspace-temp-buffer (workspace-root &rest body)
+ "With a temp-buffer under `WORKSPACE-ROOT' and evaluate `BODY', useful to access dir-local variables."
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ ;; Set the buffer's name to something under the root so that we can hack the local variables
+ ;; This file doesn't need to exist and will not be created due to this.
+ (setq-local buffer-file-name (expand-file-name "lsp-mode-temp" (expand-file-name ,workspace-root)))
+ (hack-local-variables)
+ (prog1 ,@body
+ (setq-local buffer-file-name nil))))
+
+(defun lsp--get-ignored-regexes-for-workspace-root (workspace-root)
+ "Return a list of the form (lsp-file-watch-ignored-files lsp-file-watch-ignored-directories) for the given WORKSPACE-ROOT."
+ ;; The intent of this function is to provide per-root workspace-level customization of the
+ ;; lsp-file-watch-ignored-directories and lsp-file-watch-ignored-files variables.
+ (lsp--with-workspace-temp-buffer workspace-root
+ (list lsp-file-watch-ignored-files (lsp-file-watch-ignored-directories))))
+
+
+(defun lsp--cleanup-hanging-watches ()
+ "Cleanup watches in case there are no more workspaces that are interested
+in that particular folder."
+ (let* ((session (lsp-session))
+ (watches (lsp-session-watches session)))
+ (dolist (watched-folder (ht-keys watches))
+ (when (-none? (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--registered-capability "workspace/didChangeWatchedFiles")))
+ (gethash watched-folder (lsp-session-folder->servers (lsp-session))))
+ (lsp-log "Cleaning up watches for folder %s. There is no workspace watching this folder..." watched-folder)
+ (lsp-kill-watch (gethash watched-folder watches))
+ (remhash watched-folder watches)))))
+
+(lsp-defun lsp--server-unregister-capability ((&Unregistration :id :method))
+ "Unregister capability UNREG."
+ (setf (lsp--workspace-registered-server-capabilities lsp--cur-workspace)
+ (seq-remove (lambda (e) (equal (lsp--registered-capability-id e) id))
+ (lsp--workspace-registered-server-capabilities lsp--cur-workspace)))
+ (when (equal method "workspace/didChangeWatchedFiles")
+ (lsp--cleanup-hanging-watches)))
+
+(defun lsp--server-capabilities ()
+ "Return the capabilities of the language server associated with the buffer."
+ (->> (lsp-workspaces)
+ (-keep #'lsp--workspace-server-capabilities)
+ (apply #'lsp-merge)))
+
+(defun lsp--send-open-close-p ()
+ "Return whether open and close notifications should be sent to the server."
+ (let ((sync (lsp:server-capabilities-text-document-sync? (lsp--server-capabilities))))
+ (or (memq sync '(1 2))
+ (lsp:text-document-sync-options-open-close? sync))))
+
+(defun lsp--send-will-save-p ()
+ "Return whether willSave notifications should be sent to the server."
+ (-> (lsp--server-capabilities)
+ (lsp:server-capabilities-text-document-sync?)
+ (lsp:text-document-sync-options-will-save?)))
+
+(defun lsp--send-will-save-wait-until-p ()
+ "Return whether willSaveWaitUntil notifications should be sent to the server."
+ (-> (lsp--server-capabilities)
+ (lsp:server-capabilities-text-document-sync?)
+ (lsp:text-document-sync-options-will-save-wait-until?)))
+
+(defun lsp--send-did-save-p ()
+ "Return whether didSave notifications should be sent to the server."
+ (let ((sync (lsp:server-capabilities-text-document-sync? (lsp--server-capabilities))))
+ (or (memq sync '(1 2))
+ (lsp:text-document-sync-options-save? sync))))
+
+(defun lsp--save-include-text-p ()
+ "Return whether save notifications should include the text document's contents."
+ (->> (lsp--server-capabilities)
+ (lsp:server-capabilities-text-document-sync?)
+ (lsp:text-document-sync-options-save?)
+ (lsp:text-document-save-registration-options-include-text?)))
+
+(declare-function project-roots "ext:project" (project) t)
+(declare-function project-root "ext:project" (project) t)
+
+(defun lsp--suggest-project-root ()
+ "Get project root."
+ (or
+ (when (featurep 'projectile) (condition-case nil
+ (projectile-project-root)
+ (error nil)))
+ (when (featurep 'project)
+ (when-let ((project (project-current)))
+ (if (fboundp 'project-root)
+ (project-root project)
+ (car (with-no-warnings
+ (project-roots project))))))
+ default-directory))
+
+(defun lsp--read-from-file (file)
+ "Read FILE content."
+ (when (file-exists-p file)
+ (cl-first (read-from-string (f-read-text file 'utf-8)))))
+
+(defun lsp--persist (file-name to-persist)
+ "Persist TO-PERSIST in FILE-NAME.
+
+This function creates the parent directories if they don't exist
+yet."
+ (let ((print-length nil)
+ (print-level nil))
+ ;; Create all parent directories:
+ (apply #'f-mkdir (f-split (f-parent file-name)))
+ (f-write-text (prin1-to-string to-persist) 'utf-8 file-name)))
+
+(defun lsp-workspace-folders-add (project-root)
+ "Add PROJECT-ROOT to the list of workspace folders."
+ (interactive
+ (list (read-directory-name "Select folder to add: "
+ (or (lsp--suggest-project-root) default-directory) nil t)))
+ (cl-pushnew (lsp-f-canonical project-root)
+ (lsp-session-folders (lsp-session)) :test 'equal)
+ (lsp--persist-session (lsp-session))
+
+ (run-hook-with-args 'lsp-workspace-folders-changed-functions (list project-root) nil))
+
+(defun lsp-workspace-folders-remove (project-root)
+ "Remove PROJECT-ROOT from the list of workspace folders."
+ (interactive (list (completing-read "Select folder to remove: "
+ (lsp-session-folders (lsp-session))
+ nil t nil nil
+ (lsp-find-session-folder (lsp-session) default-directory))))
+
+ (setq project-root (lsp-f-canonical project-root))
+
+ ;; send remove folder to each multiroot workspace associated with the folder
+ (dolist (wks (->> (lsp-session)
+ (lsp-session-folder->servers)
+ (gethash project-root)
+ (--filter (lsp--client-multi-root (lsp--workspace-client it)))))
+ (with-lsp-workspace wks
+ (lsp-notify "workspace/didChangeWorkspaceFolders"
+ (lsp-make-did-change-workspace-folders-params
+ :event (lsp-make-workspace-folders-change-event
+ :removed (vector (lsp-make-workspace-folder
+ :uri (lsp--path-to-uri project-root)
+ :name (f-filename project-root)))
+ :added [])))))
+
+ ;; turn off servers in the removed directory
+ (let* ((session (lsp-session))
+ (folder->servers (lsp-session-folder->servers session))
+ (server-id->folders (lsp-session-server-id->folders session))
+ (workspaces (gethash project-root folder->servers)))
+
+ (remhash project-root folder->servers)
+
+ ;; turn off the servers without root folders
+ (dolist (workspace workspaces)
+ (when (--none? (-contains? it workspace) (ht-values folder->servers))
+ (lsp--info "Shutdown %s since folder %s is removed..."
+ (lsp--workspace-print workspace) project-root)
+ (with-lsp-workspace workspace (lsp--shutdown-workspace))))
+
+ (setf (lsp-session-folders session)
+ (-remove-item project-root (lsp-session-folders session)))
+
+ (ht-aeach (puthash key
+ (-remove-item project-root value)
+ server-id->folders)
+ server-id->folders)
+ (lsp--persist-session (lsp-session)))
+
+ (run-hook-with-args 'lsp-workspace-folders-changed-functions nil (list project-root)))
+
+(defun lsp-workspace-blacklist-remove (project-root)
+ "Remove PROJECT-ROOT from the workspace blacklist."
+ (interactive (list (completing-read "Select folder to remove:"
+ (lsp-session-folders-blacklist (lsp-session))
+ nil t)))
+ (setf (lsp-session-folders-blacklist (lsp-session))
+ (delete project-root
+ (lsp-session-folders-blacklist (lsp-session))))
+ (lsp--persist-session (lsp-session)))
+
+(define-obsolete-function-alias 'lsp-workspace-folders-switch
+ 'lsp-workspace-folders-open "lsp-mode 6.1")
+
+(defun lsp-workspace-folders-open (project-root)
+ "Open the directory located at PROJECT-ROOT"
+ (interactive (list (completing-read "Open folder: "
+ (lsp-session-folders (lsp-session))
+ nil t)))
+ (find-file project-root))
+
+(defun lsp--maybe-enable-signature-help (trigger-characters)
+ (let ((ch last-command-event))
+ (when (cl-find ch trigger-characters :key #'string-to-char)
+ (lsp-signature-activate))))
+
+(defun lsp--on-type-formatting-handler-create ()
+ (when-let ((provider (lsp--capability :documentOnTypeFormattingProvider)))
+ (-let [(&DocumentOnTypeFormattingOptions :more-trigger-character?
+ :first-trigger-character) provider]
+ (lambda ()
+ (lsp--on-type-formatting first-trigger-character
+ more-trigger-character?)))))
+
+(defun lsp--update-on-type-formatting-hook (&optional cleanup?)
+ (let ((on-type-formatting-handler (lsp--on-type-formatting-handler-create)))
+ (cond
+ ((and lsp-enable-on-type-formatting on-type-formatting-handler (not cleanup?))
+ (add-hook 'post-self-insert-hook on-type-formatting-handler nil t))
+ ((or cleanup?
+ (not lsp-enable-on-type-formatting))
+ (remove-hook 'post-self-insert-hook on-type-formatting-handler t)))))
+
+(defun lsp--signature-help-handler-create ()
+ (-when-let ((&SignatureHelpOptions? :trigger-characters?)
+ (lsp--capability :signatureHelpProvider))
+ (lambda ()
+ (lsp--maybe-enable-signature-help trigger-characters?))))
+
+(defun lsp--update-signature-help-hook (&optional cleanup?)
+ (let ((signature-help-handler (lsp--signature-help-handler-create)))
+ (cond
+ ((and (or (equal lsp-signature-auto-activate t)
+ (memq :on-trigger-char lsp-signature-auto-activate))
+ signature-help-handler)
+ (add-hook 'post-self-insert-hook signature-help-handler nil t))
+
+ ((or cleanup?
+ (not (or (equal lsp-signature-auto-activate t)
+ (memq :on-trigger-char lsp-signature-auto-activate))))
+ (remove-hook 'post-self-insert-hook signature-help-handler t)))))
+
+(defun lsp--after-set-visited-file-name ()
+ (lsp-disconnect)
+ (lsp))
+
+(define-minor-mode lsp-managed-mode
+ "Mode for source buffers managed by lsp-mode."
+ :lighter nil
+ (cond
+ (lsp-managed-mode
+ (when (lsp-feature? "textDocument/hover")
+ (add-function :before-until (local 'eldoc-documentation-function) #'lsp-eldoc-function)
+ (eldoc-mode 1))
+
+ (add-hook 'after-change-functions #'lsp-on-change nil t)
+ (add-hook 'after-revert-hook #'lsp-on-revert nil t)
+ (add-hook 'after-save-hook #'lsp-on-save nil t)
+ (add-hook 'auto-save-hook #'lsp--on-auto-save nil t)
+ (add-hook 'before-change-functions #'lsp-before-change nil t)
+ (add-hook 'before-save-hook #'lsp--before-save nil t)
+ (add-hook 'kill-buffer-hook #'lsp--text-document-did-close nil t)
+ (add-hook 'post-command-hook #'lsp--post-command nil t)
+
+ (lsp--update-on-type-formatting-hook)
+ (lsp--update-signature-help-hook)
+
+ (when lsp-enable-xref
+ (add-hook 'xref-backend-functions #'lsp--xref-backend nil t))
+
+ (lsp-configure-buffer)
+
+ ;; make sure we turn off lsp-mode in case major mode changes, because major
+ ;; mode change will wipe the buffer locals.
+ (add-hook 'change-major-mode-hook #'lsp-disconnect nil t)
+ (add-hook 'after-set-visited-file-name-hook #'lsp--after-set-visited-file-name nil t)
+
+ (let ((buffer (lsp-current-buffer)))
+ (run-with-idle-timer
+ 0.0 nil
+ (lambda ()
+ (when (lsp-buffer-live-p buffer)
+ (lsp-with-current-buffer buffer
+ (lsp--on-change-debounce buffer)
+ (lsp--on-idle buffer)))))))
+ (t
+ (lsp-unconfig-buffer)
+ (remove-function (local 'eldoc-documentation-function) #'lsp-eldoc-function)
+
+ (remove-hook 'post-command-hook #'lsp--post-command t)
+ (remove-hook 'after-change-functions #'lsp-on-change t)
+ (remove-hook 'after-revert-hook #'lsp-on-revert t)
+ (remove-hook 'after-save-hook #'lsp-on-save t)
+ (remove-hook 'auto-save-hook #'lsp--on-auto-save t)
+ (remove-hook 'before-change-functions #'lsp-before-change t)
+ (remove-hook 'before-save-hook #'lsp--before-save t)
+ (remove-hook 'kill-buffer-hook #'lsp--text-document-did-close t)
+
+ (lsp--update-on-type-formatting-hook :cleanup)
+ (lsp--update-signature-help-hook :cleanup)
+
+ (when lsp--on-idle-timer
+ (cancel-timer lsp--on-idle-timer)
+ (setq lsp--on-idle-timer nil))
+
+ (remove-hook 'lsp-on-idle-hook #'lsp--document-links t)
+ (remove-hook 'lsp-on-idle-hook #'lsp--document-highlight t)
+
+ (lsp--remove-overlays 'lsp-highlight)
+ (lsp--remove-overlays 'lsp-links)
+
+ (remove-hook 'xref-backend-functions #'lsp--xref-backend t)
+ (remove-hook 'change-major-mode-hook #'lsp-disconnect t)
+ (remove-hook 'after-set-visited-file-name-hook #'lsp--after-set-visited-file-name t)
+ (setq-local lsp-buffer-uri nil))))
+
+(defun lsp-configure-buffer ()
+ "Configure LSP features for current buffer."
+ ;; make sure the core is running in the context of all available workspaces
+ ;; to avoid misconfiguration in case we are running in `with-lsp-workspace' context
+ (let ((lsp--buffer-workspaces (cond
+ (lsp--buffer-workspaces)
+ (lsp--cur-workspace (list lsp--cur-workspace))))
+ lsp--cur-workspace)
+ (when lsp-auto-configure
+ (when (and lsp-enable-text-document-color
+ (lsp-feature? "textDocument/documentColor"))
+ (add-hook 'lsp-on-change-hook #'lsp--document-color nil t))
+
+ (when (and lsp-enable-imenu
+ (lsp-feature? "textDocument/documentSymbol"))
+ (lsp-enable-imenu))
+
+ (when (and lsp-enable-indentation
+ (lsp-feature? "textDocument/rangeFormatting"))
+ (setq-local indent-region-function #'lsp-format-region))
+
+ (when (and lsp-enable-symbol-highlighting
+ (lsp-feature? "textDocument/documentHighlight"))
+ (add-hook 'lsp-on-idle-hook #'lsp--document-highlight nil t))
+
+ (when (and lsp-enable-links
+ (lsp-feature? "textDocument/documentLink"))
+ (add-hook 'lsp-on-idle-hook #'lsp--document-links nil t))
+
+ (when (and lsp-enable-dap-auto-configure
+ (functionp 'dap-mode))
+ (dap-auto-configure-mode 1)))
+ (run-hooks 'lsp-configure-hook)))
+
+(defun lsp-unconfig-buffer ()
+ "Unconfigure LSP features for buffer."
+ (run-hooks 'lsp-unconfigure-hook)
+
+ (lsp--remove-overlays 'lsp-color)
+ (when (eq indent-region-function #'lsp-format-region)
+ (setq-local indent-region-function nil))
+ (remove-hook 'lsp-on-change-hook #'lsp--document-color t)
+ (remove-hook 'lsp-on-idle-hook #'lsp--document-highlight t)
+ (remove-hook 'lsp-on-idle-hook #'lsp--document-links t))
+
+(defun lsp--buffer-content ()
+ (lsp-save-restriction-and-excursion
+ (or (lsp-virtual-buffer-call :buffer-string)
+ (buffer-substring-no-properties (point-min)
+ (point-max)))))
+
+(defun lsp--text-document-did-open ()
+ "'document/didOpen' event."
+ (run-hooks 'lsp-before-open-hook)
+ (setq lsp--cur-version (or lsp--cur-version 0))
+ (cl-pushnew (lsp-current-buffer) (lsp--workspace-buffers lsp--cur-workspace))
+ (lsp-notify
+ "textDocument/didOpen"
+ (list :textDocument
+ (list :uri (lsp--buffer-uri)
+ :languageId (lsp-buffer-language)
+ :version lsp--cur-version
+ :text (lsp--buffer-content))))
+
+ (lsp-managed-mode 1)
+
+ (run-hooks 'lsp-after-open-hook)
+ (when-let ((client (-some-> lsp--cur-workspace (lsp--workspace-client))))
+ (-some-> (lsp--client-after-open-fn client)
+ (funcall))
+ (-some-> (format "lsp-%s-after-open-hook" (lsp--client-server-id client))
+ (intern-soft)
+ (run-hooks))))
+
+(defun lsp--text-document-identifier ()
+ "Make TextDocumentIdentifier."
+ (list :uri (lsp--buffer-uri)))
+
+(defun lsp--versioned-text-document-identifier ()
+ "Make VersionedTextDocumentIdentifier."
+ (plist-put (lsp--text-document-identifier) :version lsp--cur-version))
+
+(defun lsp--cur-line (&optional point)
+ (1- (line-number-at-pos point)))
+
+(defun lsp--cur-position ()
+ "Make a Position object for the current point."
+ (or (lsp-virtual-buffer-call :cur-position)
+ (lsp-save-restriction-and-excursion
+ (list :line (lsp--cur-line)
+ :character (- (point) (line-beginning-position))))))
+
+(defun lsp--point-to-position (point)
+ "Convert POINT to Position."
+ (lsp-save-restriction-and-excursion
+ (goto-char point)
+ (lsp--cur-position)))
+
+(defun lsp--range (start end)
+ "Make Range body from START and END."
+ ;; make sure start and end are Position objects
+ (list :start start :end end))
+
+(defun lsp--region-to-range (start end)
+ "Make Range object for the current region."
+ (lsp--range (lsp--point-to-position start)
+ (lsp--point-to-position end)))
+
+(defun lsp--region-or-line ()
+ "The active region or the current line."
+ (if (use-region-p)
+ (lsp--region-to-range (region-beginning) (region-end))
+ (lsp--region-to-range (point-at-bol) (point-at-eol))))
+
+(defun lsp--check-document-changes-version (document-changes)
+ "Verify that DOCUMENT-CHANGES have the proper version."
+ (unless (seq-every-p
+ (-lambda ((&TextDocumentEdit :text-document))
+ (or
+ (not text-document)
+ (let* ((filename (-> text-document
+ lsp:versioned-text-document-identifier-uri
+ lsp--uri-to-path))
+ (version (lsp:versioned-text-document-identifier-version? text-document)))
+ (with-current-buffer (find-file-noselect filename)
+ (or (null version) (zerop version)
+ (equal version lsp--cur-version))))))
+ document-changes)
+ (error "Document changes cannot be applied")))
+
+(defun lsp--apply-workspace-edit (workspace-edit &optional operation)
+ "Apply the WorkspaceEdit object WORKSPACE-EDIT.
+OPERATION is symbol representing the source of this text edit."
+ (-let (((&WorkspaceEdit :document-changes? :changes?) workspace-edit))
+ (if-let ((document-changes (seq-reverse document-changes?)))
+ (progn
+ (lsp--check-document-changes-version document-changes)
+ (->> document-changes
+ (seq-filter (-lambda ((&CreateFile :kind))
+ (or (not kind) (equal kind "edit"))))
+ (seq-do (lambda (change) (lsp--apply-text-document-edit change operation))))
+ (->> document-changes
+ (seq-filter (-lambda ((&CreateFile :kind))
+ (not (or (not kind) (equal kind "edit")))))
+ (seq-do (lambda (change) (lsp--apply-text-document-edit change operation)))))
+ (lsp-map
+ (lambda (uri text-edits)
+ (with-current-buffer (-> uri lsp--uri-to-path find-file-noselect)
+ (lsp--apply-text-edits text-edits operation)))
+ changes?))))
+
+(defmacro lsp-with-filename (file &rest body)
+ "Execute BODY with FILE as a context.
+Need to handle the case when FILE indicates virtual buffer."
+ (declare (indent 1) (debug t))
+ `(if-let ((lsp--virtual-buffer (get-text-property 0 'lsp-virtual-buffer ,file)))
+ (lsp-with-current-buffer lsp--virtual-buffer
+ ,@body)
+ ,@body))
+
+(defun lsp--apply-text-document-edit (edit &optional operation)
+ "Apply the TextDocumentEdit object EDIT.
+OPERATION is symbol representing the source of this text edit.
+If the file is not being visited by any buffer, it is opened with
+`find-file-noselect'.
+Because lsp-mode does not store previous document versions, the edit is only
+applied if the version of the textDocument matches the version of the
+corresponding file.
+
+interface TextDocumentEdit {
+ textDocument: VersionedTextDocumentIdentifier;
+ edits: TextEdit[];
+}"
+ (pcase (lsp:edit-kind edit)
+ ("create" (-let* (((&CreateFile :uri :options?) edit)
+ (file-name (lsp--uri-to-path uri)))
+ (mkdir (f-dirname file-name) t)
+ (f-touch file-name)
+ (when (lsp:create-file-options-overwrite? options?)
+ (f-write-text "" nil file-name))))
+ ("delete" (-let (((&DeleteFile :uri :options? (&DeleteFileOptions? :recursive?)) edit))
+ (f-delete (lsp--uri-to-path uri) recursive?)))
+ ("rename" (-let* (((&RenameFile :old-uri :new-uri :options? (&RenameFileOptions? :overwrite?)) edit)
+ (old-file-name (lsp--uri-to-path old-uri))
+ (new-file-name (lsp--uri-to-path new-uri))
+ (buf (find-buffer-visiting old-file-name)))
+ (when buf
+ (lsp-with-current-buffer buf
+ (save-buffer)
+ (lsp--text-document-did-close)))
+ (mkdir (f-dirname new-file-name) t)
+ (rename-file old-file-name new-file-name overwrite?)
+ (when buf
+ (lsp-with-current-buffer buf
+ (set-buffer-modified-p nil)
+ (setq lsp-buffer-uri nil)
+ (set-visited-file-name new-file-name)
+ (lsp)))))
+ (_ (let ((file-name (->> edit
+ (lsp:text-document-edit-text-document)
+ (lsp:versioned-text-document-identifier-uri)
+ (lsp--uri-to-path))))
+ (lsp-with-current-buffer (find-buffer-visiting file-name)
+ (lsp-with-filename file-name
+ (lsp--apply-text-edits (lsp:text-document-edit-edits edit) operation)))))))
+
+(lsp-defun lsp--position-compare ((&Position :line left-line
+ :character left-character)
+ (&Position :line right-line
+ :character right-character))
+ "Return t if position LEFT is greater than RIGHT."
+ (if (= left-line right-line)
+ (> left-character right-character)
+ (> left-line right-line)))
+
+(lsp-defun lsp-point-in-range? (position (&Range :start :end))
+ "Returns if POINT is in RANGE."
+ (not (or (lsp--position-compare start position)
+ (lsp--position-compare position end))))
+
+(lsp-defun lsp--position-equal ((&Position :line left-line
+ :character left-character)
+ (&Position :line right-line
+ :character right-character))
+ "Return whether LEFT and RIGHT positions are equal."
+ (and (= left-line right-line)
+ (= left-character right-character)))
+
+(lsp-defun lsp--text-edit-sort-predicate ((&TextEdit :range (&Range :start left-start :end left-end))
+ (&TextEdit :range (&Range :start right-start :end right-end)))
+ (if (lsp--position-equal left-start right-start)
+ (lsp--position-compare left-end right-end)
+ (lsp--position-compare left-start right-start)))
+
+(lsp-defun lsp--apply-text-edit ((edit &as &TextEdit :range (&RangeToPoint :start :end) :new-text))
+ "Apply the edits described in the TextEdit object in TEXT-EDIT."
+ ;; We sort text edits so as to apply edits that modify latter parts of the
+ ;; document first. Furthermore, because the LSP spec dictates that:
+ ;; "If multiple inserts have the same position, the order in the array
+ ;; defines which edit to apply first."
+ ;; We reverse the initial list and sort stably to make sure the order among
+ ;; edits with the same position is preserved.
+ (setq new-text (s-replace "\r" "" (or new-text "")))
+ (lsp:set-text-edit-new-text edit new-text)
+ (goto-char start)
+ (delete-region start end)
+ (insert new-text))
+
+;; WORKAROUND: typescript-language might send -1 when applying code actions.
+;; see https://github.com/emacs-lsp/lsp-mode/issues/1582
+(lsp-defun lsp--fix-point ((point &as &Position :character :line))
+ (-doto point
+ (lsp:set-position-line (max 0 line))
+ (lsp:set-position-character (max 0 character))))
+
+(lsp-defun lsp--apply-text-edit-replace-buffer-contents ((edit &as
+ &TextEdit
+ :range (&Range :start :end)
+ :new-text))
+ "Apply the edits described in the TextEdit object in TEXT-EDIT.
+The method uses `replace-buffer-contents'."
+ (setq new-text (s-replace "\r" "" (or new-text "")))
+ (lsp:set-text-edit-new-text edit new-text)
+ (-let* ((source (current-buffer))
+ ((beg . end) (lsp--range-to-region (lsp-make-range :start (lsp--fix-point start)
+ :end (lsp--fix-point end)))))
+ (with-temp-buffer
+ (insert new-text)
+ (let ((temp (current-buffer)))
+ (with-current-buffer source
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+
+ ;; On emacs versions < 26.2,
+ ;; `replace-buffer-contents' is buggy - it calls
+ ;; change functions with invalid arguments - so we
+ ;; manually call the change functions here.
+ ;;
+ ;; See emacs bugs #32237, #32278:
+ ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32237
+ ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32278
+ (let ((inhibit-modification-hooks t)
+ (length (- end beg)))
+ (run-hook-with-args 'before-change-functions
+ beg end)
+ (replace-buffer-contents temp)
+ (run-hook-with-args 'after-change-functions
+ beg (+ beg (length new-text))
+ length)))))))))
+
+(defun lsp--to-yasnippet-snippet (snippet)
+ "Convert LSP SNIPPET to yasnippet snippet."
+ ;; LSP snippet doesn't escape "{" and "`", but yasnippet requires escaping it.
+ (replace-regexp-in-string (rx (or bos (not (any "$" "\\"))) (group (or "{" "`")))
+ (rx "\\" (backref 1))
+ snippet
+ nil nil 1))
+
+(defvar-local lsp-enable-relative-indentation nil
+ "Enable relative indentation when insert texts, snippets ...
+from language server.")
+
+(defun lsp--expand-snippet (snippet &optional start end expand-env)
+ "Wrapper of `yas-expand-snippet' with all of it arguments.
+The snippet will be convert to LSP style and indent according to
+LSP server result."
+ (let* ((inhibit-field-text-motion t)
+ (yas-wrap-around-region nil)
+ (yas-indent-line 'none)
+ (yas-also-auto-indent-first-line nil))
+ (yas-expand-snippet
+ (lsp--to-yasnippet-snippet snippet)
+ start end expand-env)))
+
+(defun lsp--indent-lines (start end &optional insert-text-mode?)
+ "Indent from START to END based on INSERT-TEXT-MODE? value.
+- When INSERT-TEXT-MODE? is provided
+ - if it's `lsp/insert-text-mode-as-it', do no editor indentation.
+ - if it's `lsp/insert-text-mode-adjust-indentation', adjust leading
+ whitespaces to match the line where text is inserted.
+- When it's not provided, using `indent-line-function' for each line."
+ (save-excursion
+ (goto-char end)
+ (let* ((end-line (line-number-at-pos))
+ (offset (save-excursion
+ (goto-char start)
+ (current-indentation)))
+ (indent-line-function
+ (cond ((equal insert-text-mode? lsp/insert-text-mode-as-it)
+ #'ignore)
+ ((or (equal insert-text-mode? lsp/insert-text-mode-adjust-indentation)
+ lsp-enable-relative-indentation
+ ;; Indenting snippets is extremely slow in `org-mode' buffers
+ ;; since it has to calculate indentation based on SRC block
+ ;; position. Thus we use relative indentation as default.
+ (derived-mode-p 'org-mode))
+ (lambda () (save-excursion
+ (beginning-of-line)
+ (indent-to-column offset))))
+ (t indent-line-function))))
+ (goto-char start)
+ (while (and (equal (forward-line 1) 0)
+ (<= (line-number-at-pos) end-line))
+ (funcall indent-line-function)))))
+
+(defun lsp--apply-text-edits (edits &optional operation)
+ "Apply the EDITS described in the TextEdit[] object.
+OPERATION is symbol representing the source of this text edit."
+ (unless (seq-empty-p edits)
+ (atomic-change-group
+ (run-hooks 'lsp-before-apply-edits-hook)
+ (let* ((change-group (prepare-change-group))
+ (howmany (length edits))
+ (message (format "Applying %s edits to `%s' ..." howmany (current-buffer)))
+ (_ (lsp--info message))
+ (reporter (make-progress-reporter message 0 howmany))
+ (done 0)
+ (apply-edit (if (not lsp--virtual-buffer)
+ #'lsp--apply-text-edit-replace-buffer-contents
+ #'lsp--apply-text-edit)))
+ (unwind-protect
+ (->> edits
+ (nreverse)
+ (seq-sort #'lsp--text-edit-sort-predicate)
+ (mapc (lambda (edit)
+ (progress-reporter-update reporter (cl-incf done))
+ (funcall apply-edit edit)
+ (when (lsp:snippet-text-edit-insert-text-format? edit)
+ (-when-let ((&SnippetTextEdit :range (&RangeToPoint :start)
+ :insert-text-format? :new-text) edit)
+ (when (eq insert-text-format? lsp/insert-text-format-snippet)
+ ;; No `save-excursion' needed since expand snippet will change point anyway
+ (goto-char (+ start (length new-text)))
+ (lsp--indent-lines start (point))
+ (lsp--expand-snippet new-text start (point)))))
+ (run-hook-with-args 'lsp-after-apply-edits-hook operation))))
+ (undo-amalgamate-change-group change-group)
+ (progress-reporter-done reporter))))))
+
+(defun lsp--create-apply-text-edits-handlers ()
+ "Create (handler cleanup-fn) for applying text edits in async request.
+Only works when mode is 'tick or 'alive."
+ (let* (first-edited
+ (func (lambda (start &rest _)
+ (setq first-edited (if first-edited
+ (min start first-edited)
+ start)))))
+ (add-hook 'before-change-functions func nil t)
+ (list
+ (lambda (edits)
+ (if (and first-edited
+ (seq-find (-lambda ((&TextEdit :range (&RangeToPoint :end)))
+ ;; Text edit region is overlapped
+ (> end first-edited))
+ edits))
+ (lsp--warn "TextEdits will not be applied since document has been modified before of them.")
+ (lsp--apply-text-edits edits 'completion-cleanup)))
+ (lambda ()
+ (remove-hook 'before-change-functions func t)))))
+
+(defun lsp--capability (cap &optional capabilities)
+ "Get the value of capability CAP. If CAPABILITIES is non-nil, use them instead."
+ (when (stringp cap)
+ (setq cap (intern (concat ":" cap))))
+
+ (lsp-get (or capabilities
+ (lsp--server-capabilities))
+ cap))
+
+(defun lsp--registered-capability (method)
+ "Check whether there is workspace providing METHOD."
+ (->> (lsp-workspaces)
+ (--keep (seq-find (lambda (reg)
+ (equal (lsp--registered-capability-method reg) method))
+ (lsp--workspace-registered-server-capabilities it)))
+ cl-first))
+
+(defvar-local lsp--before-change-vals nil
+ "Store the positions from the `lsp-before-change' function call, for
+validation and use in the `lsp-on-change' function.")
+
+(defun lsp--text-document-content-change-event (start end length)
+ "Make a TextDocumentContentChangeEvent body for START to END, of length LENGTH."
+ ;; So (47 54 0) means add 7 chars starting at pos 47
+ ;; must become
+ ;; {"range":{"start":{"line":5,"character":6}
+ ;; ,"end" :{"line":5,"character":6}}
+ ;; ,"rangeLength":0
+ ;; ,"text":"\nbb = 5"}
+ ;;
+ ;; And (47 47 7) means delete 7 chars starting at pos 47
+ ;; must become
+ ;; {"range":{"start":{"line":6,"character":0}
+ ;; ,"end" :{"line":7,"character":0}}
+ ;; ,"rangeLength":7
+ ;; ,"text":""}
+ ;;
+ ;; (208 221 3) means delete 3 chars starting at pos 208, and replace them with
+ ;; 13 chars. So it must become
+ ;; {"range":{"start":{"line":5,"character":8}
+ ;; ,"end" :{"line":5,"character":11}}
+ ;; ,"rangeLength":3
+ ;; ,"text":"new-chars-xxx"}
+ ;;
+
+ ;; Adding text:
+ ;; lsp-before-change:(start,end)=(33,33)
+ ;; lsp-on-change:(start,end,length)=(33,34,0)
+ ;;
+ ;; Changing text:
+ ;; lsp-before-change:(start,end)=(208,211)
+ ;; lsp-on-change:(start,end,length)=(208,221,3)
+ ;;
+ ;; Deleting text:
+ ;; lsp-before-change:(start,end)=(19,27)
+ ;; lsp-on-change:(start,end,length)=(19,19,8)
+ (if (zerop length)
+ ;; Adding something only, work from start only
+ `( :range ,(lsp--range
+ (lsp--point-to-position start)
+ (lsp--point-to-position start))
+ :rangeLength 0
+ :text ,(buffer-substring-no-properties start end))
+
+ (if (eq start end)
+ ;; Deleting something only
+ (if (lsp--bracketed-change-p start length)
+ ;; The before-change value is bracketed, use it
+ `( :range ,(lsp--range
+ (lsp--point-to-position start)
+ (plist-get lsp--before-change-vals :end-pos))
+ :rangeLength ,length
+ :text "")
+ ;; If the change is not bracketed, send a full change event instead.
+ (lsp--full-change-event))
+
+ ;; Deleting some things, adding others
+ (if (lsp--bracketed-change-p start length)
+ ;; The before-change value is valid, use it
+ `( :range ,(lsp--range
+ (lsp--point-to-position start)
+ (plist-get lsp--before-change-vals :end-pos))
+ :rangeLength ,length
+ :text ,(buffer-substring-no-properties start end))
+ (lsp--full-change-event)))))
+
+(defun lsp--bracketed-change-p (start length)
+ "If the before and after positions are the same, and the length
+is the size of the start range, we are probably good."
+ (-let [(&plist :end before-end :start before-start) lsp--before-change-vals]
+ (and (eq start before-start)
+ (eq length (- before-end before-start)))))
+
+(defun lsp--full-change-event ()
+ `(:text ,(lsp--buffer-content)))
+
+(defun lsp-before-change (start end)
+ "Executed before a file is changed.
+Added to `before-change-functions'."
+ ;; Note:
+ ;;
+ ;; This variable holds a list of functions to call when Emacs is about to
+ ;; modify a buffer. Each function gets two arguments, the beginning and end of
+ ;; the region that is about to change, represented as integers. The buffer
+ ;; that is about to change is always the current buffer when the function is
+ ;; called.
+ ;;
+ ;; WARNING:
+ ;;
+ ;; Do not expect the before-change hooks and the after-change hooks be called
+ ;; in balanced pairs around each buffer change. Also don't expect the
+ ;; before-change hooks to be called for every chunk of text Emacs is about to
+ ;; delete. These hooks are provided on the assumption that Lisp programs will
+ ;; use either before- or the after-change hooks, but not both, and the
+ ;; boundaries of the region where the changes happen might include more than
+ ;; just the actual changed text, or even lump together several changes done
+ ;; piecemeal.
+ (save-match-data
+ (lsp-save-restriction-and-excursion
+ (setq lsp--before-change-vals
+ (list :start start
+ :end end
+ :end-pos (lsp--point-to-position end))))))
+
+(defun lsp--flush-delayed-changes ()
+ (let ((inhibit-quit t))
+ (when lsp--delay-timer
+ (cancel-timer lsp--delay-timer))
+ (mapc (-lambda ((workspace buffer document change))
+ (with-current-buffer buffer
+ (with-lsp-workspace workspace
+ (lsp-notify "textDocument/didChange"
+ (list :textDocument document
+ :contentChanges (vector change))))))
+ (prog1 (nreverse lsp--delayed-requests)
+ (setq lsp--delayed-requests nil)))))
+
+(defun lsp--workspace-sync-method (workspace)
+ (let* ((sync (-> workspace
+ (lsp--workspace-server-capabilities)
+ (lsp:server-capabilities-text-document-sync?))))
+ (if (lsp-text-document-sync-options? sync)
+ (lsp:text-document-sync-options-change? sync)
+ sync)))
+
+(defun lsp-on-change (start end length &optional content-change-event-fn)
+ "Executed when a file is changed.
+Added to `after-change-functions'."
+ ;; Note:
+ ;;
+ ;; Each function receives three arguments: the beginning and end of the region
+ ;; just changed, and the length of the text that existed before the change.
+ ;; All three arguments are integers. The buffer that has been changed is
+ ;; always the current buffer when the function is called.
+ ;;
+ ;; The length of the old text is the difference between the buffer positions
+ ;; before and after that text as it was before the change. As for the
+ ;; changed text, its length is simply the difference between the first two
+ ;; arguments.
+ ;;
+ ;; So (47 54 0) means add 7 chars starting at pos 47
+ ;; So (47 47 7) means delete 7 chars starting at pos 47
+ (save-match-data
+ (let ((inhibit-quit t))
+ ;; A (revert-buffer) call with the 'preserve-modes parameter (eg, as done
+ ;; by auto-revert-mode) will cause this handler to get called with a nil
+ ;; buffer-file-name. We need the buffer-file-name to send notifications;
+ ;; so we skip handling revert-buffer-caused changes and instead handle
+ ;; reverts separately in lsp-on-revert
+ (when (not revert-buffer-in-progress-p)
+ (cl-incf lsp--cur-version)
+ (mapc
+ (lambda (workspace)
+ (pcase (or lsp-document-sync-method
+ (lsp--workspace-sync-method workspace))
+ (1
+ (if lsp-debounce-full-sync-notifications
+ (setq lsp--delayed-requests
+ (->> lsp--delayed-requests
+ (-remove (-lambda ((_ buffer))
+ (equal (current-buffer) buffer)))
+ (cons (list workspace
+ (current-buffer)
+ (lsp--versioned-text-document-identifier)
+ (lsp--full-change-event)))))
+ (with-lsp-workspace workspace
+ (lsp-notify "textDocument/didChange"
+ (list :contentChanges (vector (lsp--full-change-event))
+ :textDocument (lsp--versioned-text-document-identifier))))))
+ (2
+ (with-lsp-workspace workspace
+ (lsp-notify
+ "textDocument/didChange"
+ (list :textDocument (lsp--versioned-text-document-identifier)
+ :contentChanges (vector
+ (if content-change-event-fn
+ (funcall content-change-event-fn start end length)
+ (lsp--text-document-content-change-event
+ start end length)))))))))
+ (lsp-workspaces))
+ (when lsp--delay-timer (cancel-timer lsp--delay-timer))
+ (setq lsp--delay-timer (run-with-idle-timer
+ lsp-debounce-full-sync-notifications-interval
+ nil
+ #'lsp--flush-delayed-changes))
+ ;; force cleanup overlays after each change
+ (lsp--remove-overlays 'lsp-highlight)
+ (lsp--after-change (current-buffer))
+ (setq lsp--signature-last-index nil
+ lsp--signature-last nil)
+ ;; cleanup diagnostics
+ (when lsp-diagnostic-clean-after-change
+ (lsp-foreach-workspace
+ (-let [diagnostics (lsp--workspace-diagnostics lsp--cur-workspace)]
+ (remhash (lsp--fix-path-casing (buffer-file-name)) diagnostics))))))))
+
+
+
+;; facilities for on change hooks. We do not want to make lsp calls on each
+;; change event so we add debounce to avoid flooding the server with events.
+;; Additionally, we want to have a mechanism for stopping the server calls in
+;; particular cases like, e. g. when performing completion.
+
+(defvar lsp-inhibit-lsp-hooks nil
+ "Flag to control.")
+
+(defcustom lsp-on-change-hook nil
+ "Hooks to run when buffer has changed."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defcustom lsp-idle-delay 0.500
+ "Debounce interval for `after-change-functions'."
+ :type 'number
+ :group 'lsp-mode)
+
+(defcustom lsp-on-idle-hook nil
+ "Hooks to run after `lsp-idle-delay'."
+ :type 'hook
+ :group 'lsp-mode)
+
+(defun lsp--idle-reschedule (buffer)
+ (when lsp--on-idle-timer
+ (cancel-timer lsp--on-idle-timer))
+
+ (setq lsp--on-idle-timer (run-with-idle-timer
+ lsp-idle-delay
+ nil
+ #'lsp--on-idle
+ buffer)))
+
+(defun lsp--post-command ()
+ (lsp--cleanup-highlights-if-needed)
+ (lsp--idle-reschedule (current-buffer)))
+
+(defun lsp--on-idle (buffer)
+ "Start post command loop."
+ (when (and (buffer-live-p buffer)
+ (equal buffer (current-buffer))
+ (not lsp-inhibit-lsp-hooks)
+ lsp-managed-mode)
+ (run-hooks 'lsp-on-idle-hook)))
+
+(defun lsp--on-change-debounce (buffer)
+ (when (and (buffer-live-p buffer)
+ (equal buffer (current-buffer))
+ (not lsp-inhibit-lsp-hooks)
+ lsp-managed-mode)
+ (run-hooks 'lsp-on-change-hook)))
+
+(defun lsp--after-change (buffer)
+ (when lsp--on-change-timer
+ (cancel-timer lsp--on-change-timer))
+ (setq lsp--on-change-timer (run-with-idle-timer
+ lsp-idle-delay
+ nil
+ #'lsp--on-change-debounce
+ buffer))
+ (lsp--idle-reschedule buffer))
+
+
+
+(defun lsp--on-type-formatting (first-trigger-characters more-trigger-characters)
+ "Self insert handling.
+Applies on type formatting."
+ (let ((ch last-command-event))
+ (when (or (eq (string-to-char first-trigger-characters) ch)
+ (cl-find ch more-trigger-characters :key #'string-to-char))
+ (lsp-request-async "textDocument/onTypeFormatting"
+ (lsp-make-document-on-type-formatting-params
+ :text-document (lsp--text-document-identifier)
+ :options (lsp-make-formatting-options
+ :tab-size (symbol-value (lsp--get-indent-width major-mode))
+ :insert-spaces (if indent-tabs-mode :json-false t))
+ :ch (char-to-string ch)
+ :position (lsp--cur-position))
+ (lambda (data) (lsp--apply-text-edits data 'format))
+ :mode 'tick))))
+
+
+;; links
+(defun lsp--document-links ()
+ (when (lsp-feature? "textDocument/documentLink")
+ (lsp-request-async
+ "textDocument/documentLink"
+ `(:textDocument ,(lsp--text-document-identifier))
+ (lambda (links)
+ (lsp--remove-overlays 'lsp-link)
+ (seq-do
+ (-lambda ((link &as &DocumentLink :range (&Range :start :end)))
+ (-doto (make-button (lsp--position-to-point start)
+ (lsp--position-to-point end)
+ 'action (lsp--document-link-keymap link)
+ 'keymap (let ((map (make-sparse-keymap)))
+ (define-key map [M-return] 'push-button)
+ (define-key map [mouse-2] 'push-button)
+ map)
+ 'help-echo "mouse-2, M-RET: Visit this link")
+ (overlay-put 'lsp-link t)))
+ links))
+ :mode 'unchanged)))
+
+(defun lsp--document-link-handle-target (url)
+ (let* ((parsed-url (url-generic-parse-url (url-unhex-string url)))
+ (type (url-type parsed-url)))
+ (pcase type
+ ("file"
+ (find-file (lsp--uri-to-path url))
+ (-when-let ((_ line column) (s-match (rx "#" (group (1+ num)) "," (group (1+ num))) url))
+ (goto-char (lsp--position-to-point
+ (lsp-make-position :character (1- (string-to-number column))
+ :line (1- (string-to-number line)))))))
+ ((or "http" "https") (browse-url url))
+ (type (if-let ((handler (lsp--get-uri-handler type)))
+ (funcall handler url)
+ (signal 'lsp-file-scheme-not-supported (list url)))))))
+
+(lsp-defun lsp--document-link-keymap ((link &as &DocumentLink :target?))
+ (if target?
+ (lambda (_)
+ (interactive)
+ (lsp--document-link-handle-target target?))
+ (lambda (_)
+ (interactive)
+ (when (lsp:document-link-registration-options-resolve-provider?
+ (lsp--capability :documentLinkProvider))
+ (lsp-request-async
+ "documentLink/resolve"
+ link
+ (-lambda ((&DocumentLink :target?))
+ (lsp--document-link-handle-target target?)))))))
+
+
+
+(defun lsp-buffer-language ()
+ "Get language corresponding current buffer."
+ (or (->> lsp-language-id-configuration
+ (-first (-lambda ((mode-or-pattern . language))
+ (cond
+ ((and (stringp mode-or-pattern)
+ (s-matches? mode-or-pattern (buffer-file-name))) language)
+ ((eq mode-or-pattern major-mode) language))))
+ cl-rest)
+ (lsp-warn "Unable to calculate the languageId for buffer `%s'. Take a look at `lsp-language-id-configuration'. The `major-mode' is %s"
+ (buffer-name)
+ major-mode)))
+
+(defun lsp-activate-on (&rest languages)
+ "Returns language activation function.
+The function will return t when the `lsp-buffer-language' returns
+one of the LANGUAGES."
+ (lambda (_file-name _mode)
+ (-contains? languages (lsp-buffer-language))))
+
+(defun lsp-workspace-root (&optional path)
+ "Find the workspace root for the current file or PATH."
+ (-when-let* ((file-name (or path (buffer-file-name)))
+ (file-name (lsp-f-canonical file-name)))
+ (->> (lsp-session)
+ (lsp-session-folders)
+ (--filter (and (lsp--files-same-host it file-name)
+ (or (lsp-f-ancestor-of? it file-name)
+ (equal it file-name))))
+ (--max-by (> (length it) (length other))))))
+
+(defun lsp-on-revert ()
+ "Executed when a file is reverted.
+Added to `after-revert-hook'."
+ (let ((n (buffer-size))
+ (revert-buffer-in-progress-p nil))
+ (lsp-on-change 0 n n)))
+
+(defun lsp--text-document-did-close (&optional keep-workspace-alive)
+ "Executed when the file is closed, added to `kill-buffer-hook'.
+
+If KEEP-WORKSPACE-ALIVE is non-nil, do not shutdown the workspace
+if it's closing the last buffer in the workspace."
+ (lsp-foreach-workspace
+ (cl-callf2 delq (lsp-current-buffer) (lsp--workspace-buffers lsp--cur-workspace))
+ (with-demoted-errors "Error sending didClose notification in ‘lsp--text-document-did-close’: %S"
+ (lsp-notify "textDocument/didClose"
+ `(:textDocument ,(lsp--text-document-identifier))))
+ (when (and (not lsp-keep-workspace-alive)
+ (not keep-workspace-alive)
+ (not (lsp--workspace-buffers lsp--cur-workspace)))
+ (lsp--shutdown-workspace))))
+
+(defun lsp--will-save-text-document-params (reason)
+ (list :textDocument (lsp--text-document-identifier)
+ :reason reason))
+
+(defun lsp--before-save ()
+ "Before save handler."
+ (with-demoted-errors "Error in ‘lsp--before-save’: %S"
+ (let ((params (lsp--will-save-text-document-params 1)))
+ (when (lsp--send-will-save-p)
+ (lsp-notify "textDocument/willSave" params))
+ (when (and (lsp--send-will-save-wait-until-p) lsp-before-save-edits)
+ (let ((lsp-response-timeout 0.1))
+ (condition-case nil
+ (lsp--apply-text-edits
+ (lsp-request "textDocument/willSaveWaitUntil"
+ params)
+ 'before-save)
+ (error)))))))
+
+(defun lsp--on-auto-save ()
+ "Handler for auto-save."
+ (when (lsp--send-will-save-p)
+ (with-demoted-errors "Error in ‘lsp--on-auto-save’: %S"
+ (lsp-notify "textDocument/willSave" (lsp--will-save-text-document-params 2)))))
+
+(defun lsp--text-document-did-save ()
+ "Executed when the file is closed, added to `after-save-hook''."
+ (when (lsp--send-did-save-p)
+ (with-demoted-errors "Error on ‘lsp--text-document-did-save: %S’"
+ (lsp-notify "textDocument/didSave"
+ `( :textDocument ,(lsp--versioned-text-document-identifier)
+ ,@(when (lsp--save-include-text-p)
+ (list :text (lsp--buffer-content))))))))
+
+(defun lsp--text-document-position-params (&optional identifier position)
+ "Make TextDocumentPositionParams for the current point in the current document.
+If IDENTIFIER and POSITION are non-nil, they will be used as the document identifier
+and the position respectively."
+ (list :textDocument (or identifier (lsp--text-document-identifier))
+ :position (or position (lsp--cur-position))))
+
+(defun lsp--get-buffer-diagnostics ()
+ "Return buffer diagnostics."
+ (gethash (or
+ (plist-get lsp--virtual-buffer :buffer-file-name)
+ (lsp--fix-path-casing (buffer-file-name)))
+ (lsp-diagnostics t)))
+
+(defun lsp-cur-line-diagnostics ()
+ "Return any diagnostics that apply to the current line."
+ (-let [(&plist :start (&plist :line start) :end (&plist :line end)) (lsp--region-or-line)]
+ (cl-coerce (-filter
+ (-lambda ((&Diagnostic :range (&Range :start (&Position :line))))
+ (and (>= line start) (<= line end)))
+ (lsp--get-buffer-diagnostics))
+ 'vector)))
+
+(defalias 'lsp--cur-line-diagnotics 'lsp-cur-line-diagnostics)
+
+(defun lsp--extract-line-from-buffer (pos)
+ "Return the line pointed to by POS (a Position object) in the current buffer."
+ (let* ((point (lsp--position-to-point pos))
+ (inhibit-field-text-motion t))
+ (save-excursion
+ (goto-char point)
+ (buffer-substring (line-beginning-position) (line-end-position)))))
+
+(lsp-defun lsp--xref-make-item (filename (&Range :start (start &as &Position :character start-char :line start-line)
+ :end (end &as &Position :character end-char)))
+ "Return a xref-item from a RANGE in FILENAME."
+ (let* ((line (lsp--extract-line-from-buffer start))
+ (len (length line)))
+ (add-face-text-property (max (min start-char len) 0)
+ (max (min end-char len) 0)
+ 'highlight t line)
+ ;; LINE is nil when FILENAME is not being current visited by any buffer.
+ (xref-make (or line filename)
+ (xref-make-file-location
+ filename
+ (lsp-translate-line (1+ start-line))
+ (lsp-translate-column start-char)))))
+
+(defun lsp--location-uri (loc)
+ (if (lsp-location? loc)
+ (lsp:location-uri loc)
+ (lsp:location-link-target-uri loc)))
+
+(lsp-defun lsp-goto-location ((loc &as &Location :uri :range (&Range :start)))
+ "Go to location."
+ (let ((path (lsp--uri-to-path uri)))
+ (if (f-exists? path)
+ (with-current-buffer (find-file path)
+ (goto-char (lsp--position-to-point start)))
+ (error "There is no file %s" path))))
+
+(defun lsp--location-range (loc)
+ (if (lsp-location? loc)
+ (lsp:location-range loc)
+ (lsp:location-link-target-selection-range loc)))
+
+(defun lsp--locations-to-xref-items (locations)
+ "Return a list of `xref-item' given LOCATIONS, which can be of
+type Location, LocationLink, Location[] or LocationLink[]."
+ (setq locations
+ (pcase locations
+ ((seq (or (Location)
+ (LocationLink)))
+ (append locations nil))
+ ((or (Location)
+ (LocationLink))
+ (list locations))))
+
+ (cl-labels ((get-xrefs-in-file
+ (file-locs)
+ (-let [(filename . matches) file-locs]
+ (condition-case err
+ (let ((visiting (find-buffer-visiting filename))
+ (fn (lambda (loc)
+ (lsp-with-filename filename
+ (lsp--xref-make-item filename
+ (lsp--location-range loc))))))
+ (if visiting
+ (with-current-buffer visiting
+ (seq-map fn matches))
+ (when (file-readable-p filename)
+ (with-temp-buffer
+ (insert-file-contents-literally filename)
+ (seq-map fn matches)))))
+ (error (lsp-warn "Failed to process xref entry for filename '%s': %s"
+ filename (error-message-string err)))
+ (file-error (lsp-warn "Failed to process xref entry, file-error, '%s': %s"
+ filename (error-message-string err)))))))
+
+ (->> locations
+ (seq-sort #'lsp--location-before-p)
+ (seq-group-by (-compose #'lsp--uri-to-path #'lsp--location-uri))
+ (seq-map #'get-xrefs-in-file)
+ (apply #'nconc))))
+
+(defun lsp--location-before-p (left right)
+ "Sort first by file, then by line, then by column."
+ (let ((left-uri (lsp--location-uri left))
+ (right-uri (lsp--location-uri right)))
+ (if (not (string= left-uri right-uri))
+ (string< left-uri right-uri)
+ (-let (((&Range :start left-start) (lsp--location-range left))
+ ((&Range :start right-start) (lsp--location-range right)))
+ (lsp--position-compare right-start left-start)))))
+
+(defun lsp--make-reference-params (&optional td-position include-declaration)
+ "Make a ReferenceParam object.
+If TD-POSITION is non-nil, use it as TextDocumentPositionParams object instead.
+If INCLUDE-DECLARATION is non-nil, request the server to include declarations."
+ (let ((json-false :json-false))
+ (plist-put (or td-position (lsp--text-document-position-params))
+ :context `(:includeDeclaration ,(or include-declaration json-false)))))
+
+(defun lsp--cancel-request (id)
+ "Cancel request with ID in all workspaces."
+ (lsp-foreach-workspace
+ (->> lsp--cur-workspace lsp--workspace-client lsp--client-response-handlers (remhash id))
+ (lsp-notify "$/cancelRequest" `(:id ,id))))
+
+(defun lsp-eldoc-function ()
+ "`lsp-mode' eldoc function."
+ (run-hooks 'lsp-eldoc-hook)
+ eldoc-last-message)
+
+(defun lsp--point-on-highlight? ()
+ (-some? (lambda (overlay)
+ (overlay-get overlay 'lsp-highlight))
+ (overlays-at (point))))
+
+(defun lsp--cleanup-highlights-if-needed ()
+ (when (and lsp-enable-symbol-highlighting
+ lsp--have-document-highlights
+ (not (lsp--point-on-highlight?)))
+ (lsp--remove-overlays 'lsp-highlight)
+ (setq lsp--have-document-highlights nil)
+ (lsp-cancel-request-by-token :highlights)))
+
+(defvar-local lsp--symbol-bounds-of-last-highlight-invocation nil
+ "The bounds of the symbol from which `lsp--document-highlight'
+ most recently requested highlights.")
+
+(defun lsp--document-highlight ()
+ (let ((curr-sym-bounds (bounds-of-thing-at-point 'symbol)))
+ (unless (or (looking-at "[[:space:]\n]")
+ (not lsp-enable-symbol-highlighting)
+ (and lsp--have-document-highlights
+ curr-sym-bounds
+ (equal curr-sym-bounds
+ lsp--symbol-bounds-of-last-highlight-invocation)))
+ (setq lsp--symbol-bounds-of-last-highlight-invocation
+ curr-sym-bounds)
+ (lsp-request-async "textDocument/documentHighlight"
+ (lsp--text-document-position-params)
+ #'lsp--document-highlight-callback
+ :mode 'tick
+ :cancel-token :highlights))))
+
+(defun lsp-describe-thing-at-point ()
+ "Display the type signature and documentation of the thing at
+point."
+ (interactive)
+ (let ((contents (-some->> (lsp--text-document-position-params)
+ (lsp--make-request "textDocument/hover")
+ (lsp--send-request)
+ (lsp:hover-contents))))
+ (if (and contents (not (equal contents "")))
+ (let ((lsp-help-buf-name "*lsp-help*"))
+ (with-current-buffer (get-buffer-create lsp-help-buf-name)
+ (with-help-window lsp-help-buf-name
+ (insert (string-trim-right (lsp--render-on-hover-content contents t))))))
+ (lsp--info "No content at point."))))
+
+(defun lsp--point-in-bounds-p (bounds)
+ "Return whether the current point is within BOUNDS."
+ (and (<= (car bounds) (point)) (< (point) (cdr bounds))))
+
+(defun lsp-get-renderer (language)
+ "Get renderer for LANGUAGE."
+ (lambda (str)
+ (lsp--render-string str language)))
+
+(defun lsp--setup-markdown (mode)
+ "Setup the ‘markdown-mode’ in the frame.
+MODE is the mode used in the parent frame."
+ (make-local-variable 'markdown-code-lang-modes)
+ (dolist (mark (alist-get mode lsp-custom-markup-modes))
+ (add-to-list 'markdown-code-lang-modes (cons mark mode)))
+ (setq-local markdown-fontify-code-blocks-natively t)
+ (setq-local markdown-fontify-code-block-default-mode mode)
+ (setq-local markdown-hide-markup t)
+
+ ;; Render some common HTML entities.
+ ;; This should really happen in markdown-mode instead,
+ ;; but it doesn't, so we do it here for now.
+ (setq prettify-symbols-alist
+ (cl-loop for i from 0 to 255
+ collect (cons (format "&#x%02X;" i) i)))
+ (push '("&lt;" . ?<) prettify-symbols-alist)
+ (push '("&gt;" . ?>) prettify-symbols-alist)
+ (push '("&amp;" . ?&) prettify-symbols-alist)
+ (push '("&nbsp;" . ? ) prettify-symbols-alist)
+ (setq prettify-symbols-compose-predicate
+ (lambda (_start _end _match) t))
+ (prettify-symbols-mode 1))
+
+(defun lsp--buffer-string-visible ()
+ "Return visible buffer string.
+Stolen from `org-copy-visible'."
+ (let ((temp (generate-new-buffer " *temp*"))
+ (beg (point-min))
+ (end (point-max)))
+ (while (/= beg end)
+ (when (get-char-property beg 'invisible)
+ (setq beg (next-single-char-property-change beg 'invisible nil end)))
+ (let* ((next (next-single-char-property-change beg 'invisible nil end))
+ (substring (buffer-substring beg next)))
+ (with-current-buffer temp (insert substring))
+ ;; (setq result (concat result substring))
+ (setq beg next)))
+ (setq deactivate-mark t)
+ (prog1 (with-current-buffer temp
+ (s-chop-suffix "\n" (buffer-string)))
+ (kill-buffer temp))))
+
+(defvar lsp-buffer-major-mode nil
+ "Holds the major mode when fontification function is running.
+See #2588")
+
+(defvar view-inhibit-help-message)
+
+(defun lsp--render-markdown ()
+ "Render markdown."
+
+ (let ((markdown-enable-math nil))
+ (goto-char (point-min))
+ (while (re-search-forward
+ (rx (and "\\" (group (or "\\" "`" "*" "_" ":" "/"
+ "{" "}" "[" "]" "(" ")"
+ "#" "+" "-" "." "!" "|"))))
+ nil t)
+ (replace-match (rx (backref 1))))
+
+ ;; markdown-mode v2.3 does not yet provide gfm-view-mode
+ (if (fboundp 'gfm-view-mode)
+ (let ((view-inhibit-help-message t))
+ (gfm-view-mode))
+ (gfm-mode))
+
+ (lsp--setup-markdown lsp-buffer-major-mode)))
+
+(defvar lsp--display-inline-image-alist
+ '((lsp--render-markdown
+ (:regexp
+ "!\\[.*?\\](data:image/[a-zA-Z]+;base64,\\([A-Za-z0-9+/\n]+?=*?\\)\\(|[^)]+\\)?)"
+ :sexp
+ (create-image
+ (base64-decode-string
+ (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
+ nil t))))
+ "Replaced string regexp and function returning image.
+Each element should have the form (MODE . (PROPERTY-LIST...)).
+MODE (car) is function which is defined in `lsp-language-id-configuration'.
+Cdr should be list of PROPERTY-LIST.
+
+Each PROPERTY-LIST should have properties:
+:regexp Regexp which determines what string is relpaced to image.
+ You should also get information of image, by parenthesis constructs.
+ By default, all matched string is replaced to image, but you can
+ change index of replaced string by keyword :replaced-index.
+
+:sexp Return image when evaluated. You can use information of regexp
+ by using (match-beggining N), (match-end N) or (match-substring N).
+
+In addition, each can have property:
+:replaced-index Determine index which is used to replace regexp to image.
+ The value means first argument of `match-beginning' and
+ `match-end'. If omitted, interpreted as index 0.")
+
+(defcustom lsp-display-inline-image t
+ "Showing inline image or not."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defun lsp--display-inline-image (mode)
+ "Add image property if available."
+ (let ((plist-list (cdr (assq mode lsp--display-inline-image-alist))))
+ (when (and (display-images-p) lsp-display-inline-image)
+ (cl-loop
+ for plist in plist-list
+ with regexp with replaced-index
+ do
+ (setq regexp (plist-get plist :regexp))
+ (setq replaced-index (or (plist-get plist :replaced-index) 0))
+
+ (font-lock-remove-keywords nil (list regexp replaced-index))
+ (let ((inhibit-read-only t))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward regexp nil t)
+ (set-text-properties
+ (match-beginning replaced-index) (match-end replaced-index)
+ nil)
+ (add-text-properties
+ (match-beginning replaced-index) (match-end replaced-index)
+ `(display ,(eval (plist-get plist :sexp)))))))))))
+
+(defun lsp--fontlock-with-mode (str mode)
+ "Fontlock STR with MODE."
+ (let ((lsp-buffer-major-mode major-mode))
+ (condition-case nil
+ (with-temp-buffer
+ (insert str)
+ (delay-mode-hooks (funcall mode))
+ (cl-flet ((window-body-width () lsp-window-body-width))
+ ;; This can go wrong in some cases, and the fontification would
+ ;; not work as expected.
+ ;;
+ ;; See #2984
+ (ignore-errors (font-lock-ensure))
+ (lsp--display-inline-image mode))
+ (lsp--buffer-string-visible))
+ (error str))))
+
+(defun lsp--render-string (str language)
+ "Render STR using `major-mode' corresponding to LANGUAGE.
+When language is nil render as markup if `markdown-mode' is loaded."
+ (setq str (s-replace "\r" "" (or str "")))
+ (if-let ((mode (-some (-lambda ((mode . lang))
+ (when (and (equal lang language) (functionp mode))
+ mode))
+ lsp-language-id-configuration)))
+ (lsp--fontlock-with-mode str mode)
+ str))
+
+(defun lsp--render-element (content)
+ "Render CONTENT element."
+ (let ((inhibit-message t))
+ (or
+ (pcase content
+ ((MarkedString :value :language)
+ (lsp--render-string value language))
+ ((MarkupContent :value :kind)
+ (lsp--render-string value kind))
+ ;; plain string
+ ((pred stringp) (lsp--render-string content "markdown"))
+ ((pred null) "")
+ (_ (error "Failed to handle %s" content)))
+ "")))
+
+(defun lsp--create-unique-string-fn ()
+ (let (elements)
+ (lambda (element)
+ (let ((count (cl-count element elements :test #'string=)))
+ (prog1 (if (zerop count)
+ element
+ (format "%s (%s)" element count))
+ (push element elements))))))
+
+(defun lsp--select-action (actions)
+ "Select an action to execute from ACTIONS."
+ (cond
+ ((seq-empty-p actions) (signal 'lsp-no-code-actions nil))
+ ((and (eq (seq-length actions) 1) lsp-auto-execute-action)
+ (lsp-seq-first actions))
+ (t (let ((completion-ignore-case t))
+ (lsp--completing-read "Select code action: "
+ (seq-into actions 'list)
+ (-compose (lsp--create-unique-string-fn)
+ #'lsp:code-action-title)
+ nil t)))))
+
+(defun lsp--workspace-server-id (workspace)
+ "Return the server ID of WORKSPACE."
+ (-> workspace lsp--workspace-client lsp--client-server-id))
+
+(defun lsp--handle-rendered-for-echo-area (contents)
+ "Return a single line from RENDERED, appropriate for display in the echo area."
+ (pcase (lsp-workspaces)
+ (`(,workspace)
+ (lsp-clients-extract-signature-on-hover contents (lsp--workspace-server-id workspace)))
+ ;; For projects with multiple active workspaces we also default to
+ ;; render the first line.
+ (_ (lsp-clients-extract-signature-on-hover contents nil))))
+
+(cl-defgeneric lsp-clients-extract-signature-on-hover (contents _server-id)
+ "Extract a representative line from CONTENTS, to show in the echo area."
+ (car (s-lines (s-trim (lsp--render-element contents)))))
+
+(defun lsp--render-on-hover-content (contents render-all)
+ "Render the content received from 'document/onHover' request.
+CONTENTS - MarkedString | MarkedString[] | MarkupContent
+RENDER-ALL - nil if only the signature should be rendered."
+ (cond
+ ((lsp-markup-content? contents)
+ ;; MarkupContent.
+ ;; It tends to be long and is not suitable to display fully in the echo area.
+ ;; Just display the first line which is typically the signature.
+ (if render-all
+ (lsp--render-element contents)
+ (lsp--handle-rendered-for-echo-area contents)))
+ ((and (stringp contents) (not (string-match-p "\n" contents)))
+ ;; If the contents is a single string containing a single line,
+ ;; render it always.
+ (lsp--render-element contents))
+ (t
+ ;; MarkedString -> MarkedString[]
+ (when (or (lsp-marked-string? contents) (stringp contents))
+ (setq contents (list contents)))
+ ;; Consider the signature consisting of the elements who have a renderable
+ ;; "language" property. When render-all is nil, ignore other elements.
+ (string-join
+ (seq-map
+ #'lsp--render-element
+ (if render-all
+ contents
+ ;; Only render contents that have an available renderer.
+ (seq-filter
+ (-andfn #'lsp-marked-string?
+ (-compose #'lsp-get-renderer #'lsp:marked-string-language))
+ contents)))
+ (if (bound-and-true-p page-break-lines-mode)
+ "\n \n"
+ "\n")))))
+
+
+
+(defvar lsp-signature-mode-map
+ (-doto (make-sparse-keymap)
+ (define-key (kbd "M-n") #'lsp-signature-next)
+ (define-key (kbd "M-p") #'lsp-signature-previous)
+ (define-key (kbd "M-a") #'lsp-signature-toggle-full-docs)
+ (define-key (kbd "C-c C-k") #'lsp-signature-stop)
+ (define-key (kbd "C-g") #'lsp-signature-stop))
+ "Keymap for `lsp-signature-mode-map'.")
+
+(define-minor-mode lsp-signature-mode
+ "Mode used to show signature popup."
+ :keymap lsp-signature-mode-map
+ :lighter ""
+ :group 'lsp-mode)
+
+(defun lsp-signature-stop ()
+ "Stop showing current signature help."
+ (interactive)
+ (lsp-cancel-request-by-token :signature)
+ (remove-hook 'post-command-hook #'lsp-signature)
+ (funcall lsp-signature-function nil)
+ (lsp-signature-mode -1))
+
+(defun lsp-lv-message (message)
+ (if message
+ (progn
+ (setq lsp--signature-last-buffer (current-buffer))
+ (let ((lv-force-update t))
+ (lv-message "%s" message)))
+ (lv-delete-window)))
+
+(declare-function posframe-show "ext:posframe")
+(declare-function posframe-hide "ext:posframe")
+(declare-function posframe-poshandler-point-bottom-left-corner-upward "ext:posframe")
+
+(defface lsp-signature-posframe
+ '((t :inherit tooltip))
+ "Background and foreground for `lsp-signature-posframe'."
+ :group 'lsp-mode)
+
+(defvar lsp-signature-posframe-params
+ (list :poshandler #'posframe-poshandler-point-bottom-left-corner-upward
+ :height 6
+ :width 60
+ :border-width 10
+ :min-width 60)
+ "Params for signature and `posframe-show'.")
+
+(defun lsp-signature-posframe (str)
+ "Use posframe to show the STR signatureHelp string."
+ (if str
+ (apply #'posframe-show
+ (with-current-buffer (get-buffer-create "*lsp-signature*")
+ (erase-buffer)
+ (insert str)
+ (visual-line-mode 1)
+ (current-buffer))
+ (append lsp-signature-posframe-params
+ (list
+ :position (point)
+ :background-color (face-attribute 'lsp-signature-posframe :background nil t)
+ :foreground-color (face-attribute 'lsp-signature-posframe :foreground nil t)
+ :border-color (face-attribute 'lsp-signature-posframe :background nil t))))
+ (posframe-hide "*lsp-signature*")))
+
+(defun lsp--handle-signature-update (signature)
+ (let ((message
+ (if (lsp-signature-help? signature)
+ (lsp--signature->message signature)
+ (mapconcat #'lsp--signature->message signature "\n"))))
+ (if (s-present? message)
+ (funcall lsp-signature-function message)
+ (lsp-signature-stop))))
+
+(defun lsp-signature-activate ()
+ "Activate signature help.
+It will show up only if current point has signature help."
+ (interactive)
+ (setq lsp--signature-last nil
+ lsp--signature-last-index nil
+ lsp--signature-last-buffer (current-buffer))
+ (add-hook 'post-command-hook #'lsp-signature)
+ (lsp-signature-mode t))
+
+(defcustom lsp-signature-cycle t
+ "Whether `lsp-signature-next' and prev should cycle."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defun lsp-signature-next ()
+ "Show next signature."
+ (interactive)
+ (let ((nsigs (length (lsp:signature-help-signatures lsp--signature-last))))
+ (when (and lsp--signature-last-index
+ lsp--signature-last
+ (or lsp-signature-cycle (< (1+ lsp--signature-last-index) nsigs)))
+ (setq lsp--signature-last-index (% (1+ lsp--signature-last-index) nsigs))
+ (funcall lsp-signature-function (lsp--signature->message lsp--signature-last)))))
+
+(defun lsp-signature-previous ()
+ "Next signature."
+ (interactive)
+ (when (and lsp--signature-last-index
+ lsp--signature-last
+ (or lsp-signature-cycle (not (zerop lsp--signature-last-index))))
+ (setq lsp--signature-last-index (1- (if (zerop lsp--signature-last-index)
+ (length (lsp:signature-help-signatures lsp--signature-last))
+ lsp--signature-last-index)))
+ (funcall lsp-signature-function (lsp--signature->message lsp--signature-last))))
+
+(defun lsp-signature-toggle-full-docs ()
+ "Toggle full/partial signature documentation."
+ (interactive)
+ (let ((all? (not (numberp lsp-signature-doc-lines))))
+ (setq lsp-signature-doc-lines (if all?
+ (or (car-safe lsp-signature-doc-lines)
+ 20)
+ (list lsp-signature-doc-lines))))
+ (lsp-signature-activate))
+
+(defun lsp--signature->message (signature-help)
+ "Generate eldoc message from SIGNATURE-HELP response."
+ (setq lsp--signature-last signature-help)
+
+ (when (and signature-help (not (seq-empty-p (lsp:signature-help-signatures signature-help))))
+ (-let* (((&SignatureHelp :active-signature?
+ :active-parameter?
+ :signatures) signature-help)
+ (active-signature? (or lsp--signature-last-index active-signature? 0))
+ (_ (setq lsp--signature-last-index active-signature?))
+ ((signature &as &SignatureInformation? :label :parameters?) (seq-elt signatures active-signature?))
+ (prefix (if (= (length signatures) 1)
+ ""
+ (concat (propertize (format " %s/%s"
+ (1+ active-signature?)
+ (length signatures))
+ 'face 'success)
+ " ")))
+ (method-docs (when
+ (and lsp-signature-render-documentation
+ (or (not (numberp lsp-signature-doc-lines)) (< 0 lsp-signature-doc-lines)))
+ (let ((docs (lsp--render-element
+ (lsp:parameter-information-documentation? signature))))
+ (when (s-present? docs)
+ (concat
+ "\n"
+ (if (and (numberp lsp-signature-doc-lines)
+ (> (length (s-lines docs)) lsp-signature-doc-lines))
+ (concat (s-join "\n" (-take lsp-signature-doc-lines (s-lines docs)))
+ (propertize "\nTruncated..." 'face 'highlight))
+ docs)))))))
+ (when (and active-parameter? (not (seq-empty-p parameters?)))
+ (-when-let* ((param (when (and (< -1 active-parameter? (length parameters?)))
+ (seq-elt parameters? active-parameter?)))
+ (selected-param-label (let ((label (lsp:parameter-information-label param)))
+ (if (stringp label) label (append label nil))))
+ (start (if (stringp selected-param-label)
+ (s-index-of selected-param-label label)
+ (cl-first selected-param-label)))
+ (end (if (stringp selected-param-label)
+ (+ start (length selected-param-label))
+ (cl-second selected-param-label))))
+ (add-face-text-property start end 'eldoc-highlight-function-argument nil label)))
+ (concat prefix label method-docs))))
+
+(defun lsp-signature ()
+ "Display signature info (based on `textDocument/signatureHelp')"
+ (if (and lsp--signature-last-buffer
+ (not (equal (current-buffer) lsp--signature-last-buffer)))
+ (lsp-signature-stop)
+ (lsp-request-async "textDocument/signatureHelp"
+ (lsp--text-document-position-params)
+ #'lsp--handle-signature-update
+ :cancel-token :signature)))
+
+
+(defcustom lsp-overlay-document-color-char "â– "
+ "Display the char represent the document color in overlay"
+ :type 'string
+ :group 'lsp-mode)
+
+;; color presentation
+(defun lsp--color-create-interactive-command (color range)
+ (lambda ()
+ (interactive)
+ (-let [(&ColorPresentation? :text-edit?
+ :additional-text-edits?)
+ (lsp--completing-read
+ "Select color presentation: "
+ (lsp-request
+ "textDocument/colorPresentation"
+ `( :textDocument ,(lsp--text-document-identifier)
+ :color ,color
+ :range ,range))
+ #'lsp:color-presentation-label
+ nil
+ t)]
+ (when text-edit?
+ (lsp--apply-text-edit text-edit?))
+ (when additional-text-edits?
+ (lsp--apply-text-edits additional-text-edits? 'color-presentation)))))
+
+(defun lsp--number->color (number)
+ (let ((result (format "%x"
+ (round (* (or number 0) 255.0)))))
+ (if (= 1 (length result))
+ (concat "0" result)
+ result)))
+
+(defun lsp--document-color ()
+ "Document color handler."
+ (when (lsp-feature? "textDocument/documentColor")
+ (lsp-request-async
+ "textDocument/documentColor"
+ `(:textDocument ,(lsp--text-document-identifier))
+ (lambda (result)
+ (lsp--remove-overlays 'lsp-color)
+ (seq-do
+ (-lambda ((&ColorInformation :color (color &as &Color :red :green :blue)
+ :range))
+ (-let* (((beg . end) (lsp--range-to-region range))
+ (overlay (make-overlay beg end))
+ (command (lsp--color-create-interactive-command color range)))
+ (overlay-put overlay 'lsp-color t)
+ (overlay-put overlay 'evaporate t)
+ (overlay-put overlay
+ 'before-string
+ (propertize
+ lsp-overlay-document-color-char
+ 'face `((:foreground ,(format
+ "#%s%s%s"
+ (lsp--number->color red)
+ (lsp--number->color green)
+ (lsp--number->color blue))))
+ 'action command
+ 'mouse-face 'lsp-lens-mouse-face
+ 'local-map (-doto (make-sparse-keymap)
+ (define-key [mouse-1] command))))))
+ result))
+ :mode 'unchanged
+ :cancel-token :document-color-token)))
+
+
+;; hover
+
+(defvar-local lsp--hover-saved-bounds nil)
+
+(defun lsp-hover ()
+ "Display hover info (based on `textDocument/signatureHelp')."
+ (if (and lsp--hover-saved-bounds
+ (lsp--point-in-bounds-p lsp--hover-saved-bounds))
+ (lsp--eldoc-message lsp--eldoc-saved-message)
+ (setq lsp--hover-saved-bounds nil
+ lsp--eldoc-saved-message nil)
+ (if (looking-at "[[:space:]\n]")
+ (lsp--eldoc-message nil)
+ (when (and lsp-eldoc-enable-hover (lsp--capability :hoverProvider))
+ (lsp-request-async
+ "textDocument/hover"
+ (lsp--text-document-position-params)
+ (-lambda ((hover &as &Hover? :range? :contents))
+ (when hover
+ (when range?
+ (setq lsp--hover-saved-bounds (lsp--range-to-region range?)))
+ (lsp--eldoc-message (and contents
+ (lsp--render-on-hover-content
+ contents
+ lsp-eldoc-render-all)))))
+ :error-handler #'ignore
+ :mode 'tick
+ :cancel-token :eldoc-hover)))))
+
+
+
+(defun lsp--action-trigger-parameter-hints (_command)
+ "Handler for editor.action.triggerParameterHints."
+ (when (member :on-server-request lsp-signature-auto-activate)
+ (lsp-signature-activate)))
+
+(defun lsp--action-trigger-suggest (_command)
+ "Handler for editor.action.triggerSuggest."
+ (cond
+ ((and (bound-and-true-p company-mode)
+ (fboundp 'company-auto-begin)
+ (fboundp 'company-post-command))
+ (run-at-time 0 nil
+ (lambda ()
+ (let ((this-command 'company-idle-begin)
+ (company-minimum-prefix-length 0))
+ (company-auto-begin)
+ (company-post-command)))))
+ (t
+ (completion-at-point))))
+
+(defconst lsp--default-action-handlers
+ (ht ("editor.action.triggerParameterHints" #'lsp--action-trigger-parameter-hints)
+ ("editor.action.triggerSuggest" #'lsp--action-trigger-suggest))
+ "Default action handlers.")
+
+(defun lsp--find-action-handler (command)
+ "Find action handler for particular COMMAND."
+ (or
+ (--some (-some->> it
+ (lsp--workspace-client)
+ (lsp--client-action-handlers)
+ (gethash command))
+ (lsp-workspaces))
+ (gethash command lsp--default-action-handlers)))
+
+(defun lsp--text-document-code-action-params (&optional kind)
+ "Code action params."
+ (list :textDocument (lsp--text-document-identifier)
+ :range (if (use-region-p)
+ (lsp--region-to-range (region-beginning) (region-end))
+ (lsp--region-to-range (point) (point)))
+ :context `( :diagnostics ,(lsp-cur-line-diagnostics)
+ ,@(when kind (list :only (vector kind))))))
+
+(defun lsp-code-actions-at-point (&optional kind)
+ "Retrieve the code actions for the active region or the current line.
+It will filter by KIND if non nil."
+ (lsp-request "textDocument/codeAction" (lsp--text-document-code-action-params kind)))
+
+(defun lsp-execute-code-action-by-kind (command-kind)
+ "Execute code action by COMMAND-KIND."
+ (if-let ((action (->> (lsp-get-or-calculate-code-actions command-kind)
+ (-filter (-lambda ((&CodeAction :kind?))
+ (and kind? (equal command-kind kind?))))
+ lsp--select-action)))
+ (lsp-execute-code-action action)
+ (signal 'lsp-no-code-actions '(command-kind))))
+
+(defalias 'lsp-get-or-calculate-code-actions 'lsp-code-actions-at-point)
+
+(lsp-defun lsp--execute-command ((action &as &Command :command :arguments?))
+ "Parse and execute a code ACTION represented as a Command LSP type."
+ (let ((server-id (->> (lsp-workspaces)
+ (cl-first)
+ (or lsp--cur-workspace)
+ (lsp--workspace-client)
+ (lsp--client-server-id))))
+ (condition-case nil
+ (with-no-warnings
+ (lsp-execute-command server-id (intern command) arguments?))
+ (cl-no-applicable-method
+ (if-let ((action-handler (lsp--find-action-handler command)))
+ (funcall action-handler action)
+ (lsp-send-execute-command command arguments?))))))
+
+(lsp-defun lsp-execute-code-action ((action &as &CodeAction :command? :edit?))
+ "Execute code action ACTION.
+If ACTION is not set it will be selected from `lsp-code-actions-at-point'.
+Request codeAction/resolve for more info if server supports."
+ (interactive (list (lsp--select-action (lsp-code-actions-at-point))))
+ (if (and (lsp-feature? "codeAction/resolve")
+ (not command?)
+ (not edit?))
+ (lsp--execute-code-action (lsp-request "codeAction/resolve" action))
+ (lsp--execute-code-action action)))
+
+(lsp-defun lsp--execute-code-action ((action &as &CodeAction :command? :edit?))
+ "Execute code action ACTION."
+ (when edit?
+ (lsp--apply-workspace-edit edit? 'code-action))
+
+ (cond
+ ((stringp command?) (lsp--execute-command action))
+ ((lsp-command? command?) (lsp--execute-command command?))))
+
+(defvar lsp--formatting-indent-alist
+ ;; Taken from `dtrt-indent-mode'
+ '((c-mode . c-basic-offset) ; C
+ (c++-mode . c-basic-offset) ; C++
+ (d-mode . c-basic-offset) ; D
+ (java-mode . c-basic-offset) ; Java
+ (jde-mode . c-basic-offset) ; Java (JDE)
+ (js-mode . js-indent-level) ; JavaScript
+ (js2-mode . js2-basic-offset) ; JavaScript-IDE
+ (js3-mode . js3-indent-level) ; JavaScript-IDE
+ (json-mode . js-indent-level) ; JSON
+ (lua-mode . lua-indent-level) ; Lua
+ (objc-mode . c-basic-offset) ; Objective C
+ (php-mode . c-basic-offset) ; PHP
+ (perl-mode . perl-indent-level) ; Perl
+ (cperl-mode . cperl-indent-level) ; Perl
+ (raku-mode . raku-indent-offset) ; Perl6/Raku
+ (erlang-mode . erlang-indent-level) ; Erlang
+ (ada-mode . ada-indent) ; Ada
+ (sgml-mode . sgml-basic-offset) ; SGML
+ (nxml-mode . nxml-child-indent) ; XML
+ (pascal-mode . pascal-indent-level) ; Pascal
+ (typescript-mode . typescript-indent-level) ; Typescript
+ (sh-mode . sh-basic-offset) ; Shell Script
+ (ruby-mode . ruby-indent-level) ; Ruby
+ (enh-ruby-mode . enh-ruby-indent-level) ; Ruby
+ (crystal-mode . crystal-indent-level) ; Crystal (Ruby)
+ (css-mode . css-indent-offset) ; CSS
+ (rust-mode . rust-indent-offset) ; Rust
+ (rustic-mode . rustic-indent-offset) ; Rust
+ (scala-mode . scala-indent:step) ; Scala
+ (powershell-mode . powershell-indent) ; PowerShell
+ (ess-mode . ess-indent-offset) ; ESS (R)
+ (yaml-mode . yaml-indent-offset) ; YAML
+ (hack-mode . hack-indent-offset) ; Hack
+
+ (default . standard-indent)) ; default fallback
+ "A mapping from `major-mode' to its indent variable.")
+
+(defun lsp--get-indent-width (mode)
+ "Get indentation offset for MODE."
+ (or (alist-get mode lsp--formatting-indent-alist)
+ (lsp--get-indent-width (or (get mode 'derived-mode-parent) 'default))))
+
+(defun lsp--make-document-formatting-params ()
+ "Create document formatting params."
+ (lsp-make-document-formatting-params
+ :text-document (lsp--text-document-identifier)
+ :options (lsp-make-formatting-options
+ :tab-size (symbol-value (lsp--get-indent-width major-mode))
+ :insert-spaces (if indent-tabs-mode :json-false t))))
+
+(defun lsp-format-buffer ()
+ "Ask the server to format this document."
+ (interactive "*")
+ (cond ((lsp-feature? "textDocument/formatting")
+ (let ((edits (lsp-request "textDocument/formatting"
+ (lsp--make-document-formatting-params))))
+ (if (seq-empty-p edits)
+ (lsp--info "No formatting changes provided")
+ (lsp--apply-text-edits edits 'format))))
+ ((lsp-feature? "textDocument/rangeFormatting")
+ (save-restriction
+ (widen)
+ (lsp-format-region (point-min) (point-max))))
+ (t (signal 'lsp-capability-not-supported (list "documentFormattingProvider")))))
+
+(defun lsp-format-region (s e)
+ "Ask the server to format the region, or if none is selected, the current line."
+ (interactive "r")
+ (let ((edits (lsp-request
+ "textDocument/rangeFormatting"
+ (lsp--make-document-range-formatting-params s e))))
+ (if (seq-empty-p edits)
+ (lsp--info "No formatting changes provided")
+ (lsp--apply-text-edits edits 'format))))
+
+(defmacro lsp-make-interactive-code-action (func-name code-action-kind)
+ "Define an interactive function FUNC-NAME that attempts to
+execute a CODE-ACTION-KIND action."
+ `(defun ,(intern (concat "lsp-" (symbol-name func-name))) ()
+ ,(format "Perform the %s code action, if available." code-action-kind)
+ (interactive)
+ (condition-case nil
+ (lsp-execute-code-action-by-kind ,code-action-kind)
+ (lsp-no-code-actions
+ (when (called-interactively-p 'any)
+ (lsp--info ,(format "%s action not available" code-action-kind)))))))
+
+(lsp-make-interactive-code-action organize-imports "source.organizeImports")
+
+(defun lsp--make-document-range-formatting-params (start end)
+ "Make DocumentRangeFormattingParams for selected region."
+ (lsp:set-document-range-formatting-params-range (lsp--make-document-formatting-params)
+ (lsp--region-to-range start end)))
+
+(defconst lsp--highlight-kind-face
+ '((1 . lsp-face-highlight-textual)
+ (2 . lsp-face-highlight-read)
+ (3 . lsp-face-highlight-write)))
+
+(defun lsp--remove-overlays (name)
+ (save-restriction
+ (widen)
+ (remove-overlays (point-min) (point-max) name t)))
+
+(defun lsp-document-highlight ()
+ "Highlight all relevant references to the symbol under point."
+ (interactive)
+ (lsp--remove-overlays 'lsp-highlight) ;; clear any previous highlights
+ (setq lsp--have-document-highlights nil
+ lsp--symbol-bounds-of-last-highlight-invocation nil)
+ (let ((lsp-enable-symbol-highlighting t))
+ (lsp--document-highlight)))
+
+(defun lsp--document-highlight-callback (highlights)
+ "Create a callback to process the reply of a
+'textDocument/documentHighlight' message for the buffer BUF.
+A reference is highlighted only if it is visible in a window."
+ (lsp--remove-overlays 'lsp-highlight)
+
+ (let* ((wins-visible-pos (-map (lambda (win)
+ (cons (1- (line-number-at-pos (window-start win) t))
+ (1+ (line-number-at-pos (window-end win) t))))
+ (get-buffer-window-list nil nil 'visible))))
+ (setq lsp--have-document-highlights t)
+ (-map
+ (-lambda ((&DocumentHighlight :range (&Range :start (start &as &Position :line start-line)
+ :end (end &as &Position :line end-line))
+ :kind?))
+ (-map
+ (-lambda ((start-window . end-window))
+ ;; Make the overlay only if the reference is visible
+ (let ((start-point (lsp--position-to-point start))
+ (end-point (lsp--position-to-point end)))
+ (when (and (> (1+ start-line) start-window)
+ (< (1+ end-line) end-window)
+ (not (and lsp-symbol-highlighting-skip-current
+ (<= start-point (point) end-point))))
+ (-doto (make-overlay start-point end-point)
+ (overlay-put 'face (cdr (assq (or kind? 1) lsp--highlight-kind-face)))
+ (overlay-put 'lsp-highlight t)))))
+ wins-visible-pos))
+ highlights)))
+
+(defcustom lsp-symbol-kinds
+ '((1 . "File")
+ (2 . "Module")
+ (3 . "Namespace")
+ (4 . "Package")
+ (5 . "Class")
+ (6 . "Method")
+ (7 . "Property")
+ (8 . "Field")
+ (9 . "Constructor")
+ (10 . "Enum")
+ (11 . "Interface")
+ (12 . "Function")
+ (13 . "Variable")
+ (14 . "Constant")
+ (15 . "String")
+ (16 . "Number")
+ (17 . "Boolean")
+ (18 . "Array")
+ (19 . "Object")
+ (20 . "Key")
+ (21 . "Null")
+ (22 . "Enum Member")
+ (23 . "Struct")
+ (24 . "Event")
+ (25 . "Operator")
+ (26 . "Type Parameter"))
+ "Alist mapping SymbolKinds to human-readable strings.
+Various Symbol objects in the LSP protocol have an integral type,
+specifying what they are. This alist maps such type integrals to
+readable representations of them. See
+`https://microsoft.github.io/language-server-protocol/specifications/specification-current/',
+namespace SymbolKind."
+ :group 'lsp-mode
+ :type '(alist :key-type integer :value-type string))
+(defalias 'lsp--symbol-kind 'lsp-symbol-kinds)
+
+(lsp-defun lsp--symbol-information-to-xref
+ ((&SymbolInformation :kind :name
+ :location (&Location :uri :range (&Range :start
+ (&Position :line :character)))))
+ "Return a `xref-item' from SYMBOL information."
+ (xref-make (format "[%s] %s" (alist-get kind lsp-symbol-kinds) name)
+ (xref-make-file-location (lsp--uri-to-path uri)
+ line
+ character)))
+
+(defun lsp--get-document-symbols ()
+ "Get document symbols.
+
+If the buffer has not been modified since symbols were last
+retrieved, simply return the latest result.
+
+Else, if the request was initiated by Imenu updating its menu-bar
+entry, perform it asynchronously; i.e., give Imenu the latest
+result and then force a refresh when a new one is available.
+
+Else (e.g., due to interactive use of `imenu' or `xref'),
+perform the request synchronously."
+ (if (= (buffer-chars-modified-tick) lsp--document-symbols-tick)
+ lsp--document-symbols
+ (let ((method "textDocument/documentSymbol")
+ (params `(:textDocument ,(lsp--text-document-identifier)))
+ (tick (buffer-chars-modified-tick)))
+ (if (not lsp--document-symbols-request-async)
+ (prog1
+ (setq lsp--document-symbols (lsp-request method params))
+ (setq lsp--document-symbols-tick tick))
+ (lsp-request-async method params
+ (lambda (document-symbols)
+ (setq lsp--document-symbols document-symbols
+ lsp--document-symbols-tick tick)
+ (lsp--imenu-refresh))
+ :mode 'alive)
+ lsp--document-symbols))))
+
+(advice-add 'imenu-update-menubar :around
+ (lambda (oldfun &rest r)
+ (let ((lsp--document-symbols-request-async t))
+ (apply oldfun r))))
+
+(defun lsp--document-symbols->document-symbols-hierarchy (document-symbols current-position)
+ "Convert DOCUMENT-SYMBOLS to symbols hierarchy on CURRENT-POSITION."
+ (-let (((symbol &as &DocumentSymbol? :children?)
+ (seq-find (-lambda ((&DocumentSymbol :range))
+ (lsp-point-in-range? current-position range))
+ document-symbols)))
+ (if children?
+ (cons symbol (lsp--document-symbols->document-symbols-hierarchy children? current-position))
+ (when symbol
+ (list symbol)))))
+
+(lsp-defun lsp--symbol-information->document-symbol ((&SymbolInformation :name :kind :location :container-name? :deprecated?))
+ "Convert a SymbolInformation to a DocumentInformation"
+ (lsp-make-document-symbol :name name
+ :kind kind
+ :range (lsp:location-range location)
+ :children? nil
+ :deprecated? deprecated?
+ :selection-range (lsp:location-range location)
+ :detail? container-name?))
+
+(defun lsp--symbols-informations->document-symbols-hierarchy (symbols-informations current-position)
+ "Convert SYMBOLS-INFORMATIONS to symbols hierarchy on CURRENT-POSITION."
+ (--> symbols-informations
+ (-keep (-lambda ((symbol &as &SymbolInformation :location (&Location :range)))
+ (when (lsp-point-in-range? current-position range)
+ (lsp--symbol-information->document-symbol symbol)))
+ it)
+ (sort it (-lambda ((&DocumentSymbol :range (&Range :start a-start-position :end a-end-position))
+ (&DocumentSymbol :range (&Range :start b-start-position :end b-end-position)))
+ (and (lsp--position-compare b-start-position a-start-position)
+ (lsp--position-compare a-end-position b-end-position))))))
+
+(defun lsp--symbols->document-symbols-hierarchy (symbols)
+ "Convert SYMBOLS to symbols-hierarchy."
+ (when-let ((first-symbol (lsp-seq-first symbols)))
+ (let ((cur-position (lsp-make-position :line (plist-get (lsp--cur-position) :line)
+ :character (plist-get (lsp--cur-position) :character))))
+ (if (lsp-symbol-information? first-symbol)
+ (lsp--symbols-informations->document-symbols-hierarchy symbols cur-position)
+ (lsp--document-symbols->document-symbols-hierarchy symbols cur-position)))))
+
+(defun lsp--xref-backend () 'xref-lsp)
+
+(cl-defmethod xref-backend-identifier-at-point ((_backend (eql xref-lsp)))
+ (propertize (or (thing-at-point 'symbol) "")
+ 'identifier-at-point t))
+
+(defun lsp--xref-elements-index (symbols path)
+ (-mapcat
+ (-lambda (sym)
+ (pcase-exhaustive sym
+ ((DocumentSymbol :name :children? :selection-range (Range :start))
+ (cons (cons (concat path name)
+ (lsp--position-to-point start))
+ (lsp--xref-elements-index children? (concat path name " / "))))
+ ((SymbolInformation :name :location (Location :range (Range :start)))
+ (list (cons (concat path name)
+ (lsp--position-to-point start))))))
+ symbols))
+
+(defvar-local lsp--symbols-cache nil)
+
+(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql xref-lsp)))
+ (if (lsp--find-workspaces-for "textDocument/documentSymbol")
+ (progn
+ (setq lsp--symbols-cache (lsp--xref-elements-index
+ (lsp--get-document-symbols) nil))
+ lsp--symbols-cache)
+ (list (propertize (or (thing-at-point 'symbol) "")
+ 'identifier-at-point t))))
+
+(cl-defmethod xref-backend-definitions ((_backend (eql xref-lsp)) identifier)
+ (save-excursion
+ (unless (get-text-property 0 'identifier-at-point identifier)
+ (goto-char (cl-rest (or (assoc identifier lsp--symbols-cache)
+ (user-error "Unable to find symbol %s in current document" identifier)))))
+ (lsp--locations-to-xref-items (lsp-request "textDocument/definition"
+ (lsp--text-document-position-params)))))
+
+(cl-defmethod xref-backend-references ((_backend (eql xref-lsp)) identifier)
+ (save-excursion
+ (unless (get-text-property 0 'identifier-at-point identifier)
+ (goto-char (cl-rest (or (assoc identifier lsp--symbols-cache)
+ (user-error "Unable to find symbol %s" identifier)))))
+ (lsp--locations-to-xref-items (lsp-request "textDocument/references"
+ (lsp--make-reference-params)))))
+
+(cl-defmethod xref-backend-apropos ((_backend (eql xref-lsp)) pattern)
+ (seq-map #'lsp--symbol-information-to-xref
+ (lsp-request "workspace/symbol" `(:query ,pattern))))
+
+(defcustom lsp-rename-use-prepare t
+ "Whether `lsp-rename' should do a prepareRename first.
+For some language servers, textDocument/prepareRename might be
+too slow, in which case this variable may be set to nil.
+`lsp-rename' will then use `thing-at-point' `symbol' to determine
+the symbol to rename at point."
+ :group 'lsp-mode
+ :type 'boolean)
+
+(defun lsp--get-symbol-to-rename ()
+ "Get a symbol to rename and placeholder at point.
+Returns a cons ((START . END) . PLACEHOLDER?), and nil if
+renaming is generally supported but cannot be done at point.
+START and END are the bounds of the identifiers being renamed,
+while PLACEHOLDER?, is either nil or a string suggested by the
+language server as the initial input of a new-name prompt."
+ (unless (lsp-feature? "textDocument/rename")
+ (error "The connected server(s) doesn't support renaming"))
+ (if (and lsp-rename-use-prepare (lsp-feature? "textDocument/prepareRename"))
+ (when-let ((response
+ (lsp-request "textDocument/prepareRename"
+ (lsp--text-document-position-params))))
+ (let* ((bounds (lsp--range-to-region
+ (if (lsp-range? response)
+ response
+ (lsp:prepare-rename-result-range response))))
+ (placeholder
+ (and (not (lsp-range? response))
+ (lsp:prepare-rename-result-placeholder response))))
+ (cons bounds placeholder)))
+ (when-let ((bounds (bounds-of-thing-at-point 'symbol)))
+ (cons bounds nil))))
+
+(defface lsp-face-rename '((t :underline t))
+ "Face used to highlight the identifier being renamed.
+Renaming can be done using `lsp-rename'."
+ :group 'lsp-mode)
+
+(defface lsp-rename-placeholder-face '((t :inherit font-lock-variable-name-face))
+ "Face used to display the rename placeholder in.
+When calling `lsp-rename' interactively, this will be the face of
+the new name."
+ :group 'lsp-mode)
+
+(defvar lsp-rename-history '()
+ "History for `lsp--read-rename'.")
+
+(defun lsp--read-rename (at-point)
+ "Read a new name for a `lsp-rename' at `point' from the user.
+AT-POINT shall be a structure as returned by
+`lsp--get-symbol-to-rename'.
+
+Returns a string, which should be the new name for the identifier
+at point. If renaming cannot be done at point (as determined from
+AT-POINT), throw a `user-error'.
+
+This function is for use in `lsp-rename' only, and shall not be
+relied upon."
+ (unless at-point
+ (user-error "`lsp-rename' is invalid here"))
+ (-let* ((((start . end) . placeholder?) at-point)
+ ;; Do the `buffer-substring' first to not include `lsp-face-rename'
+ (rename-me (buffer-substring start end))
+ (placeholder (or placeholder? rename-me))
+ (placeholder (propertize placeholder 'face 'lsp-rename-placeholder-face))
+
+ overlay)
+ ;; We need unwind protect, as the user might cancel here, causing the
+ ;; overlay to linger.
+ (unwind-protect
+ (progn
+ (setq overlay (make-overlay start end))
+ (overlay-put overlay 'face 'lsp-face-rename)
+
+ (read-string (format "Rename %s to: " rename-me) placeholder
+ 'lsp-rename-history))
+ (and overlay (delete-overlay overlay)))))
+
+(defun lsp-rename (newname)
+ "Rename the symbol (and all references to it) under point to NEWNAME."
+ (interactive (list (lsp--read-rename (lsp--get-symbol-to-rename))))
+ (when-let ((edits (lsp-request "textDocument/rename"
+ `( :textDocument ,(lsp--text-document-identifier)
+ :position ,(lsp--cur-position)
+ :newName ,newname))))
+ (lsp--apply-workspace-edit edits 'rename)))
+
+(defun lsp-show-xrefs (xrefs display-action references?)
+ (unless (region-active-p) (push-mark nil t))
+ (if (boundp 'xref-show-definitions-function)
+ (with-no-warnings
+ (xref-push-marker-stack)
+ (funcall (if references? xref-show-xrefs-function xref-show-definitions-function)
+ (-const xrefs)
+ `((window . ,(selected-window))
+ (display-action . ,display-action))))
+ (xref--show-xrefs xrefs display-action)))
+
+(cl-defmethod seq-empty-p ((ht hash-table))
+ "Function `seq-empty-p' for hash-table."
+ (hash-table-empty-p ht))
+
+(cl-defun lsp-find-locations (method &optional extra &key display-action references?)
+ "Send request named METHOD and get cross references of the symbol under point.
+EXTRA is a plist of extra parameters.
+REFERENCES? t when METHOD returns references."
+ (let ((loc (lsp-request method
+ (append (lsp--text-document-position-params) extra))))
+ (if (seq-empty-p loc)
+ (lsp--error "Not found for: %s" (or (thing-at-point 'symbol t) ""))
+ (lsp-show-xrefs (lsp--locations-to-xref-items loc) display-action references?))))
+
+(cl-defun lsp-find-declaration (&key display-action)
+ "Find declarations of the symbol under point."
+ (interactive)
+ (lsp-find-locations "textDocument/declaration" nil :display-action display-action))
+
+(cl-defun lsp-find-definition (&key display-action)
+ "Find definitions of the symbol under point."
+ (interactive)
+ (lsp-find-locations "textDocument/definition" nil :display-action display-action))
+
+(defun lsp-find-definition-mouse (click)
+ "Click to start `lsp-find-definition' at clicked point."
+ (interactive "e")
+ (let* ((ec (event-start click))
+ (p1 (posn-point ec))
+ (w1 (posn-window ec)))
+ (select-window w1)
+ (goto-char p1)
+ (lsp-find-definition)))
+
+(cl-defun lsp-find-implementation (&key display-action)
+ "Find implementations of the symbol under point."
+ (interactive)
+ (lsp-find-locations "textDocument/implementation" nil :display-action display-action))
+
+(cl-defun lsp-find-references (&optional include-declaration &key display-action)
+ "Find references of the symbol under point."
+ (interactive "P")
+ (lsp-find-locations "textDocument/references"
+ (list :context `(:includeDeclaration ,(lsp-json-bool include-declaration)))
+ :display-action display-action
+ :references? t))
+
+(cl-defun lsp-find-type-definition (&key display-action)
+ "Find type definitions of the symbol under point."
+ (interactive)
+ (lsp-find-locations "textDocument/typeDefinition" nil :display-action display-action))
+
+(defalias 'lsp-find-custom #'lsp-find-locations)
+(defalias 'lsp-goto-implementation #'lsp-find-implementation)
+(defalias 'lsp-goto-type-definition #'lsp-find-type-definition)
+
+(with-eval-after-load 'evil
+ (evil-set-command-property 'lsp-find-definition :jump t)
+ (evil-set-command-property 'lsp-find-implementation :jump t)
+ (evil-set-command-property 'lsp-find-references :jump t)
+ (evil-set-command-property 'lsp-find-type-definition :jump t))
+
+(defun lsp--find-workspaces-for (msg-or-method)
+ "Find all workspaces in the current project that can handle MSG."
+ (let ((method (if (stringp msg-or-method)
+ msg-or-method
+ (plist-get msg-or-method :method))))
+ (-if-let (reqs (cdr (assoc method lsp-method-requirements)))
+ (-let (((&plist :capability :check-command) reqs))
+ (--filter
+ (with-lsp-workspace it
+ (or
+ (when check-command (funcall check-command it))
+ (when capability (lsp--capability capability))
+ (lsp--registered-capability method)
+ (and (not capability) (not check-command))))
+ (lsp-workspaces)))
+ (lsp-workspaces))))
+
+(defun lsp-can-execute-command? (command-name)
+ "Returns non-nil if current language server(s) can execute COMMAND-NAME.
+The command is executed via `workspace/executeCommand'"
+ (cl-position
+ command-name
+ (lsp:execute-command-options-commands
+ (lsp:server-capabilities-execute-command-provider?
+ (lsp--server-capabilities)))
+ :test #'equal))
+
+(defalias 'lsp-feature? 'lsp--find-workspaces-for)
+
+(cl-defmethod lsp-execute-command (_server _command _arguments)
+ "Dispatch COMMAND execution."
+ (signal 'cl-no-applicable-method nil))
+
+(defun lsp-workspace-command-execute (command &optional args)
+ "Execute workspace COMMAND with ARGS."
+ (condition-case-unless-debug err
+ (let ((params (if args
+ (list :command command :arguments args)
+ (list :command command))))
+ (lsp-request "workspace/executeCommand" params))
+ (error
+ (lsp--error "`workspace/executeCommand' with `%s' failed.\n\n%S"
+ command err))))
+
+(defun lsp-send-execute-command (command &optional args)
+ "Create and send a 'workspace/executeCommand' message having command COMMAND and optional ARGS."
+ (lsp-workspace-command-execute command args))
+
+(defalias 'lsp-point-to-position #'lsp--point-to-position)
+(defalias 'lsp-text-document-identifier #'lsp--text-document-identifier)
+(defalias 'lsp--send-execute-command #'lsp-send-execute-command)
+(defalias 'lsp-on-open #'lsp--text-document-did-open)
+(defalias 'lsp-on-save #'lsp--text-document-did-save)
+
+(defun lsp--set-configuration (settings)
+ "Set the SETTINGS for the lsp server."
+ (lsp-notify "workspace/didChangeConfiguration" `(:settings ,settings)))
+
+(defun lsp-current-buffer ()
+ (or lsp--virtual-buffer
+ (current-buffer)))
+
+(defun lsp-buffer-live-p (buffer-id)
+ (if-let ((buffer-live (plist-get buffer-id :buffer-live?)))
+ (funcall buffer-live buffer-id)
+ (buffer-live-p buffer-id)))
+
+(defun lsp--on-set-visited-file-name (old-func &rest args)
+ "Advice around function `set-visited-file-name'.
+
+This advice sends textDocument/didClose for the old file and
+textDocument/didOpen for the new file."
+ (when lsp--cur-workspace
+ (lsp--text-document-did-close t))
+ (prog1 (apply old-func args)
+ (when lsp--cur-workspace
+ (lsp--text-document-did-open))))
+
+(advice-add 'set-visited-file-name :around #'lsp--on-set-visited-file-name)
+
+(defvar lsp--flushing-delayed-changes nil)
+
+(defun lsp--send-no-wait (message proc)
+ "Send MESSAGE to PROC without waiting for further output."
+
+ (unless lsp--flushing-delayed-changes
+ (let ((lsp--flushing-delayed-changes t))
+ (lsp--flush-delayed-changes)))
+
+ (condition-case err
+ (process-send-string proc message)
+ ('error (lsp--error "Sending to process failed with the following error: %s"
+ (error-message-string err)))))
+
+(define-error 'lsp-parse-error
+ "Error parsing message from language server" 'lsp-error)
+(define-error 'lsp-unknown-message-type
+ "Unknown message type" '(lsp-error lsp-parse-error))
+(define-error 'lsp-unknown-json-rpc-version
+ "Unknown JSON-RPC protocol version" '(lsp-error lsp-parse-error))
+(define-error 'lsp-no-content-length
+ "Content-Length header missing in message" '(lsp-error lsp-parse-error))
+(define-error 'lsp-invalid-header-name
+ "Invalid header name" '(lsp-error lsp-parse-error))
+
+;; id method
+;; x x request
+;; x . response
+;; . x notification
+(defun lsp--get-message-type (json-data)
+ "Get the message type from JSON-DATA."
+ (if (lsp:json-message-id? json-data)
+ (if (lsp:json-message-error? json-data)
+ 'response-error
+ (if (lsp:json-message-method? json-data)
+ 'request
+ 'response))
+ 'notification))
+
+(defconst lsp--default-notification-handlers
+ (ht ("window/showMessage" #'lsp--window-show-message)
+ ("window/logMessage" #'lsp--window-log-message)
+ ("textDocument/publishDiagnostics" #'lsp--on-diagnostics)
+ ("textDocument/diagnosticsEnd" #'ignore)
+ ("textDocument/diagnosticsBegin" #'ignore)
+ ("telemetry/event" #'ignore)
+ ("$/progress" (lambda (workspace params)
+ (funcall lsp-progress-function workspace params)))))
+
+(lsp-defun lsp--on-notification (workspace (&JSONNotification :params :method))
+ "Call the appropriate handler for NOTIFICATION."
+ (-let ((client (lsp--workspace-client workspace)))
+ (when lsp-print-io
+ (lsp--log-entry-new (lsp--make-log-entry method nil params 'incoming-notif)
+ lsp--cur-workspace))
+ (if-let ((handler (or (gethash method (lsp--client-notification-handlers client))
+ (gethash method lsp--default-notification-handlers))))
+ (funcall handler workspace params)
+ (when (and method (not (string-prefix-p "$" method)))
+ (lsp-warn "Unknown notification: %s" method)))))
+
+(lsp-defun lsp--build-workspace-configuration-response ((&ConfigurationParams :items))
+ "Get section configuration.
+PARAMS are the `workspace/configuration' request params"
+ (->> items
+ (-map (-lambda ((&ConfigurationItem :section?))
+ (-let* ((path-parts (split-string section? "\\."))
+ (path-without-last (s-join "." (-slice path-parts 0 -1)))
+ (path-parts-len (length path-parts)))
+ (cond
+ ((<= path-parts-len 1)
+ (ht-get (lsp-configuration-section section?)
+ (car-safe path-parts)
+ (ht-create)))
+ ((> path-parts-len 1)
+ (when-let ((section (lsp-configuration-section path-without-last))
+ (keys path-parts))
+ (while (and keys section)
+ (setf section (ht-get section (pop keys))))
+ section))))))
+ (apply #'vector)))
+
+(defun lsp--send-request-response (workspace recv-time request response)
+ "Send the RESPONSE for REQUEST in WORKSPACE and log if needed."
+ (-let* (((&JSONResponse :params :method :id) request)
+ (process (lsp--workspace-proc workspace))
+ (response (lsp--make-response id response))
+ (req-entry (and lsp-print-io
+ (lsp--make-log-entry method id params 'incoming-req)))
+ (resp-entry (and lsp-print-io
+ (lsp--make-log-entry method id response 'outgoing-resp
+ (/ (nth 2 (time-since recv-time)) 1000)))))
+ ;; Send response to the server.
+ (when lsp-print-io
+ (lsp--log-entry-new req-entry workspace)
+ (lsp--log-entry-new resp-entry workspace))
+ (lsp--send-no-wait (lsp--make-message response) process)))
+
+(lsp-defun lsp--on-request (workspace (request &as &JSONRequest :params :method))
+ "Call the appropriate handler for REQUEST, and send the return value to the server.
+WORKSPACE is the active workspace."
+ (-let* ((recv-time (current-time))
+ (client (lsp--workspace-client workspace))
+ (buffers (lsp--workspace-buffers workspace))
+ handler
+ (response (cond
+ ((setq handler (gethash method (lsp--client-request-handlers client) nil))
+ (funcall handler workspace params))
+ ((setq handler (gethash method (lsp--client-async-request-handlers client) nil))
+ (funcall handler workspace params
+ (-partial #'lsp--send-request-response
+ workspace recv-time request))
+ 'delay-response)
+ ((equal method "client/registerCapability")
+ (mapc #'lsp--server-register-capability
+ (lsp:registration-params-registrations params))
+ (mapc (lambda (buf)
+ (when (lsp-buffer-live-p buf)
+ (lsp-with-current-buffer buf
+ (lsp-unconfig-buffer)
+ (lsp-configure-buffer))))
+ buffers)
+ nil)
+ ((equal method "window/showMessageRequest")
+ (let ((choice (lsp--window-log-message-request params)))
+ `(:title ,choice)))
+ ((equal method "client/unregisterCapability")
+ (mapc #'lsp--server-unregister-capability
+ (lsp:unregistration-params-unregisterations params))
+ (mapc (lambda (buf)
+ (when (lsp-buffer-live-p buf)
+ (lsp-with-current-buffer buf
+ (lsp-unconfig-buffer)
+ (lsp-configure-buffer))))
+ buffers)
+ nil)
+ ((equal method "workspace/applyEdit")
+ (list :applied (condition-case err
+ (prog1 t
+ (lsp--apply-workspace-edit (lsp:apply-workspace-edit-params-edit params) 'server-requested))
+ (error
+ (lsp--error "Failed to apply edits with message %s"
+ (error-message-string err))
+ :json-false))))
+ ((equal method "workspace/configuration")
+ (with-lsp-workspace workspace
+ (if-let ((buf (car buffers)))
+ (lsp-with-current-buffer buf
+ (lsp--build-workspace-configuration-response params))
+ (lsp--with-workspace-temp-buffer (lsp--workspace-root workspace)
+ (lsp--build-workspace-configuration-response params)))))
+ ((equal method "workspace/workspaceFolders")
+ (let ((folders (or (-> workspace
+ (lsp--workspace-client)
+ (lsp--client-server-id)
+ (gethash (lsp-session-server-id->folders (lsp-session))))
+ (lsp-session-folders (lsp-session)))))
+ (->> folders
+ (-distinct)
+ (-map (lambda (folder)
+ (list :uri (lsp--path-to-uri folder))))
+ (apply #'vector))))
+ ((equal method "window/workDoneProgress/create")
+ nil ;; no specific reply, no processing required
+ )
+ ((equal method "workspace/semanticTokens/refresh")
+ (when (and lsp-semantic-tokens-enable
+ (fboundp 'lsp--semantic-tokens-on-refresh))
+ (lsp--semantic-tokens-on-refresh))
+ nil)
+ (t (lsp-warn "Unknown request method: %s" method) nil))))
+ ;; Send response to the server.
+ (unless (eq response 'delay-response)
+ (lsp--send-request-response workspace recv-time request response))))
+
+(lsp-defun lsp--error-string ((&JSONError :message :code))
+ "Format ERR as a user friendly string."
+ (format "Error from the Language Server: %s (%s)"
+ message
+ (or (car (alist-get code lsp--errors)) "Unknown error")))
+
+(defun lsp--get-body-length (headers)
+ (let ((content-length (cdr (assoc "Content-Length" headers))))
+ (if content-length
+ (string-to-number content-length)
+
+ ;; This usually means either the server or our parser is
+ ;; screwed up with a previous Content-Length
+ (error "No Content-Length header"))))
+
+(defun lsp--parse-header (s)
+ "Parse string S as a LSP (KEY . VAL) header."
+ (let ((pos (string-match "\:" s))
+ key val)
+ (unless pos
+ (signal 'lsp-invalid-header-name (list s)))
+ (setq key (substring s 0 pos)
+ val (s-trim-left (substring s (+ 1 pos))))
+ (when (equal key "Content-Length")
+ (cl-assert (cl-loop for c across val
+ when (or (> c ?9) (< c ?0)) return nil
+ finally return t)
+ nil (format "Invalid Content-Length value: %s" val)))
+ (cons key val)))
+
+(defmacro lsp--read-json (str)
+ "Read json string STR."
+ (if (progn
+ (require 'json)
+ (fboundp 'json-parse-string))
+ `(json-parse-string ,str
+ :object-type (if lsp-use-plists
+ 'plist
+ 'hash-table)
+ :null-object nil
+ :false-object nil)
+ `(let ((json-array-type 'vector)
+ (json-object-type (if lsp-use-plists
+ 'plist
+ 'hash-table))
+ (json-false nil))
+ (json-read-from-string ,str))))
+
+(defmacro lsp-json-read-buffer ()
+ "Read json from the current buffer."
+ (if (progn
+ (require 'json)
+ (fboundp 'json-parse-string))
+ `(json-parse-buffer :object-type (if lsp-use-plists
+ 'plist
+ 'hash-table)
+ :null-object nil
+ :false-object nil)
+ `(let ((json-array-type 'vector)
+ (json-object-type (if lsp-use-plists
+ 'plist
+ 'hash-table))
+ (json-false nil))
+ (json-read))))
+
+(defun lsp--read-json-file (file-path)
+ "Read json file."
+ (-> file-path
+ (f-read-text)
+ (lsp--read-json)))
+
+(defun lsp--parser-on-message (json-data workspace)
+ "Called when the parser P read a complete MSG from the server."
+ (with-demoted-errors "Error processing message %S."
+ (with-lsp-workspace workspace
+ (let* ((client (lsp--workspace-client workspace))
+ (id (--when-let (lsp:json-response-id json-data)
+ (if (stringp it) (string-to-number it) it)))
+ (data (lsp:json-response-result json-data)))
+ (pcase (lsp--get-message-type json-data)
+ ('response
+ (cl-assert id)
+ (-let [(callback _ method _ before-send) (gethash id (lsp--client-response-handlers client))]
+ (when lsp-print-io
+ (lsp--log-entry-new
+ (lsp--make-log-entry method id data 'incoming-resp
+ (/ (nth 2 (time-since before-send)) 1000))
+ workspace))
+ (when callback
+ (funcall callback (lsp:json-response-result json-data))
+ (remhash id (lsp--client-response-handlers client)))))
+ ('response-error
+ (cl-assert id)
+ (-let [(_ callback method _ before-send) (gethash id (lsp--client-response-handlers client))]
+ (when lsp-print-io
+ (lsp--log-entry-new
+ (lsp--make-log-entry method id (lsp:json-response-error-error json-data)
+ 'incoming-resp (/ (nth 2 (time-since before-send)) 1000))
+ workspace))
+ (when callback
+ (funcall callback (lsp:json-response-error-error json-data))
+ (remhash id (lsp--client-response-handlers client)))))
+ ('notification
+ (lsp--on-notification workspace json-data))
+ ('request (lsp--on-request workspace json-data)))))))
+
+(defvar lsp-parsed-message nil
+ "This will store the string representation of the json message.
+
+In some cases like #1807 we lose information during json
+deserialization.")
+
+(defun lsp--create-filter-function (workspace)
+ "Make filter for the workspace."
+ (let ((body-received 0)
+ leftovers body-length body chunk)
+ (lambda (_proc input)
+ (setf chunk (if (s-blank? leftovers)
+ input
+ (concat leftovers input)))
+
+ (let (messages)
+ (while (not (s-blank? chunk))
+ (if (not body-length)
+ ;; Read headers
+ (if-let ((body-sep-pos (string-match-p "\r\n\r\n" chunk)))
+ ;; We've got all the headers, handle them all at once:
+ (setf body-length (lsp--get-body-length
+ (mapcar #'lsp--parse-header
+ (split-string
+ (substring-no-properties chunk
+ (or (string-match-p "Content-Length" chunk)
+ (error "Unable to find Content-Length header."))
+ body-sep-pos)
+ "\r\n")))
+ body-received 0
+ leftovers nil
+ chunk (substring-no-properties chunk (+ body-sep-pos 4)))
+
+ ;; Haven't found the end of the headers yet. Save everything
+ ;; for when the next chunk arrives and await further input.
+ (setf leftovers chunk
+ chunk nil))
+ (let* ((chunk-length (string-bytes chunk))
+ (left-to-receive (- body-length body-received))
+ (this-body (if (< left-to-receive chunk-length)
+ (prog1 (substring-no-properties chunk 0 left-to-receive)
+ (setf chunk (substring-no-properties chunk left-to-receive)))
+ (prog1 chunk
+ (setf chunk nil))))
+ (body-bytes (string-bytes this-body)))
+ (push this-body body)
+ (setf body-received (+ body-received body-bytes))
+ (when (>= chunk-length left-to-receive)
+ (condition-case err
+ (with-temp-buffer
+ (apply #'insert
+ (nreverse
+ (prog1 body
+ (setf leftovers nil
+ body-length nil
+ body-received nil
+ body nil))))
+ (decode-coding-region (point-min)
+ (point-max)
+ 'utf-8)
+ (goto-char (point-min))
+ (push (lsp-json-read-buffer) messages))
+
+ (error
+ (lsp-warn "Failed to parse the following chunk:\n'''\n%s\n'''\nwith message %s"
+ (concat leftovers input)
+ err)))))))
+ (mapc (lambda (msg)
+ (lsp--parser-on-message msg workspace))
+ (nreverse messages))))))
+
+(defvar-local lsp--line-col-to-point-hash-table nil
+ "Hash table with keys (line . col) and values that are either point positions
+or markers.")
+
+(defcustom lsp-imenu-detailed-outline t
+ "Whether `lsp-imenu' should include signatures.
+This will be ignored if the server doesn't provide the necessary
+information, for example if it doesn't support DocumentSymbols."
+ :group 'lsp-imenu
+ :type 'boolean)
+
+(defface lsp-details-face '((t :height 0.8 :inherit shadow))
+ "Used to display additional information troughout `lsp'.
+Things like line numbers, signatures, ... are considered
+additional information. Often, additional faces are defined that
+inherit from this face by default, like `lsp-signature-face', and
+they may be customized for finer control."
+ :group 'lsp-mode)
+
+(defface lsp-signature-face '((t :inherit lsp-details-face))
+ "Used to display signatures in `imenu', ...."
+ :group 'lsp-mode)
+
+(lsp-defun lsp-render-symbol ((&DocumentSymbol :name :detail? :deprecated?)
+ show-detail?)
+ "Render INPUT0, an `&DocumentSymbol', to a string.
+If SHOW-DETAIL? is set, make use of its `:detail?' field (often
+the signature)."
+ (let ((detail (and show-detail? (s-present? detail?)
+ (propertize (concat " " (s-trim-left detail?))
+ 'face 'lsp-signature-face)))
+ (name (if deprecated?
+ (propertize name 'face 'lsp-face-semhl-deprecated) name)))
+ (concat name detail)))
+
+(lsp-defun lsp-render-symbol-information ((&SymbolInformation :name :deprecated? :container-name?)
+ separator)
+ "Render a piece of SymbolInformation.
+Handle :deprecated?. If SEPARATOR is non-nil, the
+symbol's (optional) parent, SEPARATOR and the symbol itself are
+concatenated."
+ (when (and separator container-name? (not (string-empty-p container-name?)))
+ (setq name (concat name separator container-name?)))
+ (if deprecated? (propertize name 'face 'lsp-face-semhl-deprecated) name))
+
+(defun lsp--symbol-to-imenu-elem (sym)
+ "Convert SYM to imenu element.
+
+SYM is a SymbolInformation message.
+
+Return a cons cell (full-name . start-point)."
+ (let ((start-point (ht-get lsp--line-col-to-point-hash-table
+ (lsp--get-line-and-col sym))))
+ (cons (lsp-render-symbol-information
+ sym (and lsp-imenu-show-container-name
+ lsp-imenu-container-name-separator))
+ start-point)))
+
+(lsp-defun lsp--symbol-to-hierarchical-imenu-elem ((sym &as &DocumentSymbol :children?))
+ "Convert SYM to hierarchical imenu elements.
+
+SYM is a DocumentSymbol message.
+
+Return cons cell (\"symbol-name (symbol-kind)\" . start-point) if
+SYM doesn't have any children. Otherwise return a cons cell with
+an alist
+
+ (\"symbol-name\" . ((\"(symbol-kind)\" . start-point)
+ cons-cells-from-children))"
+ (let ((filtered-children (lsp--imenu-filter-symbols children?))
+ (signature (lsp-render-symbol sym lsp-imenu-detailed-outline)))
+ (if (seq-empty-p filtered-children)
+ (cons signature
+ (ht-get lsp--line-col-to-point-hash-table
+ (lsp--get-line-and-col sym)))
+ (cons signature
+ (lsp--imenu-create-hierarchical-index filtered-children)))))
+
+(lsp-defun lsp--symbol-ignore ((&SymbolInformation :kind :location))
+ "Determine if SYM is for the current document and is to be shown."
+ ;; It's a SymbolInformation or DocumentSymbol, which is always in the
+ ;; current buffer file.
+ (or (and lsp-imenu-index-symbol-kinds
+ (numberp kind)
+ (let ((clamped-kind (if (< 0 kind (length lsp/symbol-kind-lookup))
+ kind
+ 0)))
+ (not (memql (aref lsp/symbol-kind-lookup clamped-kind)
+ lsp-imenu-index-symbol-kinds))))
+ (and location
+ (not (eq (->> location
+ (lsp:location-uri)
+ (lsp--uri-to-path)
+ (find-buffer-visiting))
+ (current-buffer))))))
+
+(lsp-defun lsp--get-symbol-type ((&SymbolInformation :kind))
+ "The string name of the kind of SYM."
+ (alist-get kind lsp-symbol-kinds "Other"))
+
+(defun lsp--get-line-and-col (sym)
+ "Obtain the line and column corresponding to SYM."
+ (-let* ((location (lsp:symbol-information-location sym))
+ (name-range (or (and location (lsp:location-range location))
+ (lsp:document-symbol-selection-range sym)))
+ ((&Range :start (&Position :line :character)) name-range))
+ (cons line character)))
+
+(defun lsp--collect-lines-and-cols (symbols)
+ "Return a sorted list ((line . col) ...) of the locations of SYMBOLS."
+ (let ((stack (mapcar 'identity symbols))
+ line-col-list)
+ (while stack
+ (let ((sym (pop stack)))
+ (push (lsp--get-line-and-col sym) line-col-list)
+ (unless (seq-empty-p (lsp:document-symbol-children? sym))
+ (setf stack (nconc (lsp--imenu-filter-symbols (lsp:document-symbol-children? sym)) stack)))))
+ (-sort #'lsp--line-col-comparator line-col-list)))
+
+(defun lsp--convert-line-col-to-points-batch (line-col-list)
+ "Convert a sorted list of positions from line-column
+representation to point representation."
+ (let ((line-col-to-point-map (ht-create))
+ (inhibit-field-text-motion t)
+ (curr-line 0))
+ (lsp-save-restriction-and-excursion
+ (goto-char (point-min))
+ (cl-loop for (line . col) in line-col-list do
+ (forward-line (- line curr-line))
+ (setq curr-line line)
+ (let ((line-end (line-end-position)))
+ (if (or (not col) (> col (- line-end (point))))
+ (goto-char line-end)
+ (forward-char col)))
+ (ht-set! line-col-to-point-map (cons line col) (if imenu-use-markers
+ (point-marker)
+ (point)))))
+ line-col-to-point-map))
+
+(cl-defun lsp--line-col-comparator ((l1 . c1) (l2 . c2))
+ (or (< l1 l2)
+ (and (= l1 l2)
+ (cond ((and c1 c2)
+ (< c1 c2))
+ (c1 t)))))
+
+(defun lsp-imenu-create-uncategorized-index (symbols)
+ "Create imenu index from document SYMBOLS.
+This function, unlike `lsp-imenu-create-categorized-index', does
+not categorize by type, but instead returns an `imenu' index
+corresponding to the symbol hierarchy returned by the server
+directly."
+ (let* ((lsp--line-col-to-point-hash-table (-> symbols
+ lsp--collect-lines-and-cols
+ lsp--convert-line-col-to-points-batch)))
+ (if (lsp--imenu-hierarchical-p symbols)
+ (lsp--imenu-create-hierarchical-index symbols)
+ (lsp--imenu-create-non-hierarchical-index symbols))))
+
+(defcustom lsp-imenu-symbol-kinds
+ '((1 . "Files")
+ (2 . "Modules")
+ (3 . "Namespaces")
+ (4 . "Packages")
+ (5 . "Classes")
+ (6 . "Methods")
+ (7 . "Properties")
+ (8 . "Fields")
+ (9 . "Constructors")
+ (10 . "Enums")
+ (11 . "Interfaces")
+ (12 . "Functions")
+ (13 . "Variables")
+ (14 . "Constants")
+ (15 . "Strings")
+ (16 . "Numbers")
+ (17 . "Booleans")
+ (18 . "Arrays")
+ (19 . "Objects")
+ (20 . "Keys")
+ (21 . "Nulls")
+ (22 . "Enum Members")
+ (23 . "Structs")
+ (24 . "Events")
+ (25 . "Operators")
+ (26 . "Type Parameters"))
+ "`lsp-symbol-kinds', but only used by `imenu'.
+A new variable is needed, as it is `imenu' convention to use
+pluralized categories, which `lsp-symbol-kinds' doesn't. If the
+non-pluralized names are preferred, this can be set to
+`lsp-symbol-kinds'."
+ :type '(alist :key-type integer :value-type string))
+
+(defun lsp--imenu-kind->name (kind)
+ (alist-get kind lsp-imenu-symbol-kinds "?"))
+
+(defun lsp-imenu-create-top-level-categorized-index (symbols)
+ "Create an `imenu' index categorizing SYMBOLS by type.
+Only root symbols are categorized.
+
+See `lsp-symbol-kinds' to customize the category naming. SYMBOLS
+shall be a list of DocumentSymbols or SymbolInformation."
+ (mapcan
+ (-lambda ((type . symbols))
+ (let ((cat (lsp--imenu-kind->name type))
+ (symbols (lsp-imenu-create-uncategorized-index symbols)))
+ ;; If there is no :kind (this is being defensive), or we couldn't look it
+ ;; up, just display the symbols inline, without categories.
+ (if cat (list (cons cat symbols)) symbols)))
+ (sort (seq-group-by #'lsp:document-symbol-kind symbols)
+ (-lambda ((kinda) (kindb)) (< kinda kindb)))))
+
+(lsp-defun lsp--symbol->imenu ((sym &as &DocumentSymbol :selection-range (&RangeToPoint :start)))
+ "Convert an `&DocumentSymbol' to an `imenu' entry."
+ (cons (lsp-render-symbol sym lsp-imenu-detailed-outline) start))
+
+(defun lsp--imenu-create-categorized-index-1 (symbols)
+ "Returns an `imenu' index from SYMBOLS categorized by type.
+The result looks like this: ((\"Variables\" . (...)))."
+ (->>
+ symbols
+ (mapcan
+ (-lambda ((sym &as &DocumentSymbol :kind :children?))
+ (if (seq-empty-p children?)
+ (list (list kind (lsp--symbol->imenu sym)))
+ (let ((parent (lsp-render-symbol sym lsp-imenu-detailed-outline)))
+ (cons
+ (list kind (lsp--symbol->imenu sym))
+ (mapcar (-lambda ((type . imenu-items))
+ (list type (cons parent (mapcan #'cdr imenu-items))))
+ (-group-by #'car (lsp--imenu-create-categorized-index-1 children?))))))))
+ (-group-by #'car)
+ (mapcar
+ (-lambda ((kind . syms))
+ (cons kind (mapcan #'cdr syms))))))
+
+(defun lsp--imenu-create-categorized-index (symbols)
+ (let ((syms (lsp--imenu-create-categorized-index-1 symbols)))
+ (dolist (sym syms)
+ (setcar sym (lsp--imenu-kind->name (car sym))))
+ syms))
+
+(lsp-defun lsp--symbol-information->imenu ((sym &as &SymbolInformation :location (&Location :range (&RangeToPoint :start))))
+ (cons (lsp-render-symbol-information sym nil) start))
+
+(defun lsp--imenu-create-categorized-index-flat (symbols)
+ "Create a kind-categorized index for SymbolInformation."
+ (mapcar (-lambda ((kind . syms))
+ (cons (lsp--imenu-kind->name kind)
+ (mapcan (-lambda ((parent . children))
+ (let ((children (mapcar #'lsp--symbol-information->imenu children)))
+ (if parent (list (cons parent children)) children)))
+ (-group-by #'lsp:symbol-information-container-name? syms))))
+ (seq-group-by #'lsp:symbol-information-kind symbols)))
+
+(defun lsp-imenu-create-categorized-index (symbols)
+ (if (lsp--imenu-hierarchical-p symbols)
+ (lsp--imenu-create-categorized-index symbols)
+ (lsp--imenu-create-categorized-index-flat symbols)))
+
+(defcustom lsp-imenu-index-function #'lsp-imenu-create-uncategorized-index
+ "Function that should create an `imenu' index.
+It will be called with a list of SymbolInformation or
+DocumentSymbols, whose first level is already filtered. It shall
+then return an appropriate `imenu' index (see
+`imenu-create-index-function').
+
+Note that this interface is not stable, and subject to change any
+time."
+ :group 'lsp-imenu
+ :type '(radio
+ (const :tag "Categorize by type"
+ lsp-imenu-create-categorized-index)
+ (const :tag "Categorize root symbols by type"
+ lsp-imenu-create-top-level-categorized-index)
+ (const :tag "Uncategorized, inline entries"
+ lsp-imenu-create-uncategorized-index)
+ (function :tag "Custom function")))
+
+(defun lsp--imenu-create-index ()
+ "Create an `imenu' index based on the language server.
+Respects `lsp-imenu-index-function'."
+ (let ((symbols (lsp--imenu-filter-symbols (lsp--get-document-symbols))))
+ (funcall lsp-imenu-index-function symbols)))
+
+(defun lsp--imenu-filter-symbols (symbols)
+ "Filter out unsupported symbols from SYMBOLS."
+ (seq-remove #'lsp--symbol-ignore symbols))
+
+(defun lsp--imenu-hierarchical-p (symbols)
+ "Determine whether any element in SYMBOLS has children."
+ (seq-some #'lsp-document-symbol? symbols))
+
+(defun lsp--imenu-create-non-hierarchical-index (symbols)
+ "Create imenu index for non-hierarchical SYMBOLS.
+
+SYMBOLS are a list of DocumentSymbol messages.
+
+Return a nested alist keyed by symbol names. e.g.
+
+ ((\"SomeClass\" (\"(Class)\" . 10)
+ (\"someField (Field)\" . 20)
+ (\"someFunction (Function)\" . 25)
+ (\"SomeSubClass\" (\"(Class)\" . 30)
+ (\"someSubField (Field)\" . 35))
+ (\"someFunction (Function)\" . 40))"
+ (seq-map (lambda (nested-alist)
+ (cons (car nested-alist)
+ (seq-map #'lsp--symbol-to-imenu-elem (cdr nested-alist))))
+ (seq-group-by #'lsp--get-symbol-type symbols)))
+
+(defun lsp--imenu-create-hierarchical-index (symbols)
+ "Create imenu index for hierarchical SYMBOLS.
+
+SYMBOLS are a list of DocumentSymbol messages.
+
+Return a nested alist keyed by symbol names. e.g.
+
+ ((\"SomeClass\" (\"(Class)\" . 10)
+ (\"someField (Field)\" . 20)
+ (\"someFunction (Function)\" . 25)
+ (\"SomeSubClass\" (\"(Class)\" . 30)
+ (\"someSubField (Field)\" . 35))
+ (\"someFunction (Function)\" . 40))"
+ (seq-map #'lsp--symbol-to-hierarchical-imenu-elem
+ (seq-sort #'lsp--imenu-symbol-lessp symbols)))
+
+(defun lsp--imenu-symbol-lessp (sym1 sym2)
+ (let* ((compare-results (mapcar (lambda (method)
+ (funcall (alist-get method lsp--imenu-compare-function-alist)
+ sym1 sym2))
+ lsp-imenu-sort-methods))
+ (result (seq-find (lambda (result)
+ (not (= result 0)))
+ compare-results
+ 0)))
+ (and (numberp result) (< result 0))))
+
+(lsp-defun lsp--imenu-compare-kind ((&SymbolInformation :kind left)
+ (&SymbolInformation :kind right))
+ "Compare SYM1 and SYM2 by kind."
+ (- left right))
+
+(defun lsp--imenu-compare-line-col (sym1 sym2)
+ (if (lsp--line-col-comparator
+ (lsp--get-line-and-col sym1)
+ (lsp--get-line-and-col sym2))
+ -1
+ 1))
+
+(lsp-defun lsp--imenu-compare-name ((&SymbolInformation :name name1)
+ (&SymbolInformation :name name2))
+ "Compare SYM1 and SYM2 by name."
+ (let ((result (compare-strings name1 0 (length name1) name2 0 (length name2))))
+ (if (numberp result) result 0)))
+
+(defun lsp--imenu-refresh ()
+ "Force Imenu to refresh itself."
+ (imenu--menubar-select imenu--rescan-item))
+
+(defun lsp-enable-imenu ()
+ "Use lsp-imenu for the current buffer."
+ (imenu--cleanup)
+ (setq-local imenu-create-index-function #'lsp--imenu-create-index)
+ (setq-local imenu-menubar-modified-tick -1)
+ (setq-local imenu--index-alist nil)
+ (when menu-bar-mode
+ (lsp--imenu-refresh)))
+
+(defun lsp-resolve-final-function (command)
+ "Resolve final function COMMAND."
+ (-let [command (if (functionp command) (funcall command) command)]
+ (cl-etypecase command
+ (list
+ (cl-assert (seq-every-p (apply-partially #'stringp) command) nil
+ "Invalid command list")
+ command)
+ (string (list command)))))
+
+(defun lsp-server-present? (final-command)
+ "Check whether FINAL-COMMAND is present."
+ ;; executable-find only gained support for remote checks after 27 release
+ (or (and (cond
+ ((not (file-remote-p default-directory))
+ (executable-find (cl-first final-command)))
+ ((version<= "27.0" emacs-version)
+ (with-no-warnings (executable-find (cl-first final-command) (file-remote-p default-directory))))
+ (t))
+ (prog1 t
+ (lsp-log "Command \"%s\" is present on the path." (s-join " " final-command))))
+ (ignore (lsp-log "Command \"%s\" is not present on the path." (s-join " " final-command)))))
+
+(defun lsp--value-to-string (value)
+ "Convert VALUE to a string that can be set as value in an environment variable."
+ (cond
+ ((stringp value) value)
+ ((booleanp value) (if value
+ "1"
+ "0"))
+ ((and (sequencep value)
+ (seq-every-p #'stringp value)) (string-join value ":"))
+ (t (user-error "Only strings, booleans, and sequences of strings are supported as environment variables"))))
+
+(defun lsp--compute-process-environment (environment-fn)
+ "Append a list of KEY=VALUE from the alist ENVIRONMENT to `process-environment'.
+Ignore non-boolean keys whose value is nil."
+ (let ((environment (if environment-fn
+ (funcall environment-fn)
+ nil)))
+ (-flatten (cons (cl-loop for (key . value) in environment
+ if (or (eval value)
+ (eq (get value 'custom-type) 'boolean))
+ collect (concat key "=" (lsp--value-to-string
+ (eval value))))
+ process-environment))))
+
+(defun lsp-stdio-connection (command &optional test-command)
+ "Returns a connection property list using COMMAND.
+COMMAND can be: A string, denoting the command to launch the
+language server. A list of strings, denoting an executable with
+its command line arguments. A function, that either returns a
+string or a list of strings. In all cases, the launched language
+server should send and receive messages on standard I/O.
+TEST-COMMAND is a function with no arguments which returns
+whether the command is present or not. When not specified
+`lsp-mode' will check whether the first element of the list
+returned by COMMAND is available via `executable-find'"
+ (cl-check-type command (or string
+ function
+ (and list
+ (satisfies (lambda (l)
+ (seq-every-p (lambda (el)
+ (stringp el))
+ l))))))
+ (list :connect (lambda (filter sentinel name environment-fn)
+ (let ((final-command (lsp-resolve-final-function command))
+ (process-name (generate-new-buffer-name name))
+ (process-environment
+ (lsp--compute-process-environment environment-fn)))
+ (let* ((stderr-buf (format "*%s::stderr*" process-name))
+ (proc (make-process
+ :name process-name
+ :connection-type 'pipe
+ :buffer (format "*%s*" process-name)
+ :coding 'no-conversion
+ :command final-command
+ :filter filter
+ :sentinel sentinel
+ :stderr stderr-buf
+ :noquery t)))
+ (set-process-query-on-exit-flag proc nil)
+ (set-process-query-on-exit-flag (get-buffer-process stderr-buf) nil)
+ (with-current-buffer (get-buffer stderr-buf)
+ ;; Make the *NAME::stderr* buffer buffer-read-only, q to bury, etc.
+ (special-mode))
+ (cons proc proc))))
+ :test? (or
+ test-command
+ (lambda () (-> command lsp-resolve-final-function lsp-server-present?)))))
+
+(defun lsp--open-network-stream (host port name)
+ "Open network stream to HOST:PORT.
+ NAME will be passed to `open-network-stream'.
+ RETRY-COUNT is the number of the retries.
+ SLEEP-INTERVAL is the sleep interval between each retry."
+ (let* ((retries 0)
+ (sleep-interval 0.01)
+ (number-of-retries (/ lsp-tcp-connection-timeout sleep-interval))
+ connection)
+ (while (and (not connection) (< retries number-of-retries))
+ (condition-case err
+ (setq connection (open-network-stream name nil host port
+ :type 'plain
+ :coding 'no-conversion))
+ (file-error
+ (let ((inhibit-message t))
+ (lsp--warn "Failed to connect to %s:%s with error message %s"
+ host
+ port
+ (error-message-string err))
+ (sleep-for sleep-interval)
+ (cl-incf retries)))))
+ (or connection (error "Port %s was never taken. Consider increasing `lsp-tcp-connection-timeout'." port))))
+
+(defun lsp--find-available-port (host starting-port)
+ "Find available port on HOST starting from STARTING-PORT."
+ (let ((success nil)
+ (port starting-port))
+ (while (and (not success))
+ (condition-case _err
+ (progn
+ (delete-process (open-network-stream "*connection-test*" nil host port :type 'plain))
+ (cl-incf port))
+ (file-error (setq success t))))
+ port))
+
+(defun lsp-tcp-connection (command-fn)
+ "Returns a connection property list similar to `lsp-stdio-connection'.
+COMMAND-FN can only be a function that takes a single argument, a
+port number. It should return a command for launches a language server
+process listening for TCP connections on the provided port."
+ (cl-check-type command-fn function)
+ (list
+ :connect (lambda (filter sentinel name environment-fn)
+ (let* ((host "localhost")
+ (port (lsp--find-available-port host (cl-incf lsp--tcp-port)))
+ (command (funcall command-fn port))
+ (final-command (if (consp command) command (list command)))
+ (_ (unless (executable-find (cl-first final-command))
+ (user-error (format "Couldn't find executable %s" (cl-first final-command)))))
+ (process-environment
+ (lsp--compute-process-environment environment-fn))
+ (proc (make-process :name name :connection-type 'pipe :coding 'no-conversion
+ :command final-command :sentinel sentinel :stderr (format "*%s::stderr*" name) :noquery t))
+ (tcp-proc (lsp--open-network-stream host port (concat name "::tcp"))))
+
+ ;; TODO: Same :noquery issue (see above)
+ (set-process-query-on-exit-flag proc nil)
+ (set-process-query-on-exit-flag tcp-proc nil)
+ (set-process-filter tcp-proc filter)
+ (cons tcp-proc proc)))
+ :test? (lambda () (executable-find (cl-first (funcall command-fn 0))))))
+
+(defalias 'lsp-tcp-server 'lsp-tcp-server-command)
+
+(defun lsp-tcp-server-command (command-fn)
+ "Create tcp server connection.
+In this mode Emacs is TCP server and the language server connects
+to it. COMMAND is function with one parameter(the port) and it
+should return the command to start the LS server."
+ (cl-check-type command-fn function)
+ (list
+ :connect (lambda (filter sentinel name environment-fn)
+ (let* (tcp-client-connection
+ (tcp-server (make-network-process :name (format "*tcp-server-%s*" name)
+ :buffer (format "*tcp-server-%s*" name)
+ :family 'ipv4
+ :service lsp--tcp-server-port
+ :sentinel (lambda (proc _string)
+ (lsp-log "Language server %s is connected." name)
+ (setf tcp-client-connection proc))
+ :server 't))
+ (port (process-contact tcp-server :service))
+ (final-command (funcall command-fn port))
+ (process-environment
+ (lsp--compute-process-environment environment-fn))
+ (cmd-proc (make-process :name name
+ :connection-type 'pipe
+ :coding 'no-conversion
+ :command final-command
+ :stderr (format "*tcp-server-%s*::stderr" name)
+ :noquery t)))
+ (let ((retries 0))
+ ;; wait for the client to connect (we sit-for 500 ms, so have to double lsp--tcp-server-wait-seconds)
+ (while (and (not tcp-client-connection) (< retries (* 2 lsp--tcp-server-wait-seconds)))
+ (lsp--info "Waiting for connection for %s, retries: %s" name retries)
+ (sit-for 0.500)
+ (cl-incf retries)))
+
+ (unless tcp-client-connection
+ (condition-case nil (delete-process tcp-server) (error))
+ (condition-case nil (delete-process cmd-proc) (error))
+ (error "Failed to create connection to %s on port %s" name port))
+ (lsp--info "Successfully connected to %s" name)
+
+ (set-process-query-on-exit-flag cmd-proc nil)
+ (set-process-query-on-exit-flag tcp-client-connection nil)
+ (set-process-query-on-exit-flag tcp-server nil)
+
+ (set-process-filter tcp-client-connection filter)
+ (set-process-sentinel tcp-client-connection sentinel)
+ (cons tcp-client-connection cmd-proc)))
+ :test? (lambda () (executable-find (cl-first (funcall command-fn 0))))))
+
+(defun lsp-tramp-connection (local-command &optional generate-error-file-fn)
+ "Create LSP stdio connection named name.
+LOCAL-COMMAND is either list of strings, string or function which
+returns the command to execute."
+ (list :connect (lambda (filter sentinel name environment-fn)
+ (let* ((final-command (lsp-resolve-final-function local-command))
+ ;; wrap with stty to disable converting \r to \n
+ (process-name (generate-new-buffer-name name))
+ (wrapped-command (s-join
+ " "
+ (append '("stty" "raw" ";")
+ final-command
+ (list
+ (concat "2>"
+ (or (when generate-error-file-fn
+ (funcall generate-error-file-fn name))
+ (format "/tmp/%s-%s-stderr" name
+ (cl-incf lsp--stderr-index))))))))
+ (process-environment
+ (lsp--compute-process-environment environment-fn)))
+ (let ((proc (start-file-process-shell-command process-name
+ (format "*%s*" process-name)
+ wrapped-command)))
+ (set-process-sentinel proc sentinel)
+ (set-process-filter proc filter)
+ (set-process-query-on-exit-flag proc nil)
+ (set-process-coding-system proc 'binary 'binary)
+ (cons proc proc))))
+ :test? (lambda () (-> local-command lsp-resolve-final-function lsp-server-present?))))
+
+(defun lsp--auto-configure ()
+ "Autoconfigure `company', `flycheck', `lsp-ui', etc if they are installed."
+ (when (functionp 'lsp-ui-mode)
+ (lsp-ui-mode))
+
+ (when lsp-headerline-breadcrumb-enable
+ (add-hook 'lsp-configure-hook 'lsp-headerline-breadcrumb-mode))
+ (when lsp-modeline-code-actions-enable
+ (add-hook 'lsp-configure-hook 'lsp-modeline-code-actions-mode))
+ (when lsp-modeline-diagnostics-enable
+ (add-hook 'lsp-configure-hook 'lsp-modeline-diagnostics-mode))
+ (when lsp-modeline-workspace-status-enable
+ (add-hook 'lsp-configure-hook 'lsp-modeline-workspace-status-mode))
+ (when lsp-lens-enable
+ (add-hook 'lsp-configure-hook 'lsp-lens--enable))
+ (when lsp-semantic-tokens-enable
+ (add-hook 'lsp-configure-hook 'lsp-semantic-tokens--enable))
+
+ ;; yas-snippet config
+ (setq-local yas-inhibit-overlay-modification-protection t))
+
+(defvar-local lsp--buffer-deferred nil
+ "Whether buffer was loaded via `lsp-deferred'.")
+
+(defun lsp--restart-if-needed (workspace)
+ "Handler restart for WORKSPACE."
+ (when (or (eq lsp-restart 'auto-restart)
+ (eq (lsp--workspace-shutdown-action workspace) 'restart)
+ (and (eq lsp-restart 'interactive)
+ (let ((query (format
+ "Server %s exited with status %s(check corresponding stderr buffer for details). Do you want to restart it?"
+ (lsp--workspace-print workspace)
+ (process-status (lsp--workspace-proc workspace)))))
+ (y-or-n-p query))))
+ (--each (lsp--workspace-buffers workspace)
+ (when (lsp-buffer-live-p it)
+ (lsp-with-current-buffer it
+ (if lsp--buffer-deferred
+ (lsp-deferred)
+ (lsp--info "Restarting LSP in buffer %s" (buffer-name))
+ (lsp)))))))
+
+(defun lsp--update-key (table key fn)
+ "Apply FN on value corresponding to KEY in TABLE."
+ (let ((existing-value (gethash key table)))
+ (if-let ((new-value (funcall fn existing-value)))
+ (puthash key new-value table)
+ (remhash key table))))
+
+(defun lsp--process-sentinel (workspace process exit-str)
+ "Create the sentinel for WORKSPACE."
+ (unless (process-live-p process)
+ (let* ((status (process-status process))
+ (folder->workspaces (lsp-session-folder->servers (lsp-session)))
+ (stderr (-> workspace lsp--workspace-proc process-name get-buffer)))
+
+ (lsp--warn "%s has exited (%s)"
+ (process-name (lsp--workspace-proc workspace))
+ (string-trim-right exit-str))
+
+ (with-lsp-workspace workspace
+ ;; Clean workspace related data in each of the buffers
+ ;; in the workspace.
+ (--each (lsp--workspace-buffers workspace)
+ (when (lsp-buffer-live-p it)
+ (lsp-with-current-buffer it
+ (setq lsp--buffer-workspaces (delete workspace lsp--buffer-workspaces))
+ (lsp--uninitialize-workspace)
+ (lsp--spinner-stop)
+ (lsp--remove-overlays 'lsp-highlight))))
+
+ ;; Cleanup session from references to the closed workspace.
+ (--each (hash-table-keys folder->workspaces)
+ (lsp--update-key folder->workspaces it (apply-partially 'delete workspace)))
+
+ ;; Kill standard error buffer only if the process exited normally.
+ ;; Leave it intact otherwise for debugging purposes.
+ (when (and (eq status 'exit) (zerop (process-exit-status process)) (buffer-live-p stderr))
+ (kill-buffer stderr)))
+
+ (run-hook-with-args 'lsp-after-uninitialized-functions workspace)
+
+ (if (eq (lsp--workspace-shutdown-action workspace) 'shutdown)
+ (lsp--info "Workspace %s shutdown." (lsp--workspace-print workspace))
+ (lsp--restart-if-needed workspace))
+ (lsp--cleanup-hanging-watches))))
+
+(defun lsp-workspace-folders (workspace)
+ "Return all folders associated with WORKSPACE."
+ (let (result)
+ (->> (lsp-session)
+ (lsp-session-folder->servers)
+ (maphash (lambda (folder workspaces)
+ (when (-contains? workspaces workspace)
+ (push folder result)))))
+ result))
+
+(defun lsp--start-workspace (session client-template root &optional initialization-options)
+ "Create new workspace for CLIENT-TEMPLATE with project root ROOT.
+INITIALIZATION-OPTIONS are passed to initialize function.
+SESSION is the active session."
+ (lsp--spinner-start)
+ (-let* ((default-directory root)
+ (client (copy-lsp--client client-template))
+ (workspace (make-lsp--workspace
+ :root root
+ :client client
+ :status 'starting
+ :buffers (list (lsp-current-buffer))
+ :host-root (file-remote-p root)))
+ ((&lsp-cln 'server-id 'environment-fn 'new-connection 'custom-capabilities
+ 'multi-root 'initialized-fn) client)
+ ((proc . cmd-proc) (funcall
+ (or (plist-get new-connection :connect)
+ (user-error "Client %s is configured incorrectly" client))
+ (lsp--create-filter-function workspace)
+ (apply-partially #'lsp--process-sentinel workspace)
+ (format "%s" server-id)
+ environment-fn))
+ (workspace-folders (gethash server-id (lsp-session-server-id->folders session))))
+ (setf (lsp--workspace-proc workspace) proc
+ (lsp--workspace-cmd-proc workspace) cmd-proc)
+
+ ;; update (lsp-session-folder->servers) depending on whether we are starting
+ ;; multi/single folder workspace
+ (mapc (lambda (project-root)
+ (->> session
+ (lsp-session-folder->servers)
+ (gethash project-root)
+ (cl-pushnew workspace)))
+ (or workspace-folders (list root)))
+
+ (with-lsp-workspace workspace
+ (run-hooks 'lsp-before-initialize-hook)
+ (lsp-request-async
+ "initialize"
+ (append
+ (list :processId nil
+ :rootPath (lsp-file-local-name (expand-file-name root))
+ :clientInfo (list :name "emacs"
+ :version (emacs-version))
+ :rootUri (lsp--path-to-uri root)
+ :capabilities (lsp--client-capabilities custom-capabilities)
+ :initializationOptions initialization-options
+ :workDoneToken "1")
+ (when lsp-server-trace
+ (list :trace lsp-server-trace))
+ (when multi-root
+ (->> workspace-folders
+ (-distinct)
+ (-map (lambda (folder)
+ (list :uri (lsp--path-to-uri folder)
+ :name (f-filename folder))))
+ (apply 'vector)
+ (list :workspaceFolders))))
+ (lambda (response)
+ (unless response
+ (lsp--spinner-stop)
+ (signal 'lsp-empty-response-error (list "initialize")))
+
+ (let* ((capabilities (lsp:initialize-result-capabilities response))
+ (json-object-type 'hash-table)
+ (text-document-sync (-some-> lsp-parsed-message
+ (json-read-from-string)
+ (ht-get "result")
+ (ht-get "capabilities")
+ (ht-get "textDocumentSync")))
+ (save (when (ht? text-document-sync)
+ (ht-get text-document-sync "save"))))
+ ;; see #1807
+ (when (and (ht? save) (ht-empty? save))
+ (-> capabilities
+ (lsp:server-capabilities-text-document-sync?)
+ (lsp:set-text-document-sync-options-save? save)))
+
+ (setf (lsp--workspace-server-capabilities workspace) capabilities
+ (lsp--workspace-status workspace) 'initialized)
+
+ (with-lsp-workspace workspace
+ (lsp-notify "initialized" lsp--empty-ht))
+
+ (when initialized-fn (funcall initialized-fn workspace))
+
+ (cl-callf2 -filter #'lsp-buffer-live-p (lsp--workspace-buffers workspace))
+ (->> workspace
+ (lsp--workspace-buffers)
+ (mapc (lambda (buffer)
+ (lsp-with-current-buffer buffer
+ (lsp--open-in-workspace workspace)))))
+
+ (with-lsp-workspace workspace
+ (run-hooks 'lsp-after-initialize-hook))
+ (lsp--info "%s initialized successfully in folders: %s"
+ (lsp--workspace-print workspace)
+ (lsp-workspace-folders workspace))))
+ :mode 'detached))
+ workspace))
+
+(defun lsp--load-default-session ()
+ "Load default session."
+ (setq lsp--session (or (condition-case err
+ (lsp--read-from-file lsp-session-file)
+ (error (lsp--error "Failed to parse the session %s, starting with clean one."
+ (error-message-string err))
+ nil))
+ (make-lsp-session))))
+
+(defun lsp-session ()
+ "Get the session associated with the current buffer."
+ (or lsp--session (setq lsp--session (lsp--load-default-session))))
+
+(defun lsp--client-disabled-p (buffer-major-mode client)
+ (seq-some
+ (lambda (entry)
+ (pcase entry
+ ((pred symbolp) (eq entry client))
+ (`(,mode . ,client-or-list)
+ (and (eq mode buffer-major-mode)
+ (if (listp client-or-list)
+ (memq client client-or-list)
+ (eq client client-or-list))))))
+ lsp-disabled-clients))
+
+
+;; download server
+
+(defcustom lsp-server-install-dir (expand-file-name
+ (locate-user-emacs-file (f-join ".cache" "lsp")))
+ "Directory in which the servers will be installed."
+ :risky t
+ :type 'directory
+ :package-version '(lsp-mode . "6.3")
+ :group 'lsp-mode)
+
+(defcustom lsp-verify-signature t
+ "Whether to check GPG signatures of downloaded files."
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1")
+ :group 'lsp-mode)
+
+(defvar lsp--dependencies (ht))
+
+(defun lsp-dependency (name &rest definitions)
+ "Used to specify a language server DEPENDENCY, the server
+executable or other required file path. Typically, the
+DEPENDENCY is found by locating it on the system path using
+`executable-find'.
+
+You can explicitly call lsp-dependency in your environment to
+specify the absolute path to the DEPENDENCY. For example, the
+typescript-language-server requires both the server and the
+typescript compiler. If you've installed them in a team shared
+read-only location, you can instruct lsp-mode to use them via
+
+ (eval-after-load 'lsp-mode
+ '(progn
+ (require 'lsp-javascript)
+ (lsp-dependency 'typescript-language-server `(:system ,tls-exe))
+ (lsp-dependency 'typescript `(:system ,ts-js))))
+
+where tls-exe is the absolute path to the typescript-language-server
+executable and ts-js is the absolute path to the typescript compiler
+JavaScript file, tsserver.js (the *.js is required for Windows)."
+ (ht-set lsp--dependencies name definitions))
+
+(defun lsp--server-binary-present? (client)
+ (unless (equal (lsp--client-server-id client) 'lsp-pwsh)
+ (condition-case ()
+ (-some-> client lsp--client-new-connection (plist-get :test?) funcall)
+ (error nil)
+ (args-out-of-range nil))))
+
+(define-minor-mode lsp-installation-buffer-mode
+ "Mode used in *lsp-installation* buffers.
+It can be used to set-up keybindings, etc. Disabling this mode
+detaches the installation buffer from commands like
+`lsp-select-installation-buffer'."
+ :init-value nil
+ :lighter nil)
+
+(defface lsp-installation-finished-buffer-face '((t :foreground "orange"))
+ "Face used for finished installation buffers.
+Used in `lsp-select-installation-buffer'."
+ :group 'lsp-mode)
+
+(defface lsp-installation-buffer-face '((t :foreground "green"))
+ "Face used for installation buffers still in progress.
+Used in `lsp-select-installation-buffer'."
+ :group 'lsp-mode)
+
+(defun lsp--installation-buffer? (buf)
+ "Check whether BUF is an `lsp-async-start-process' buffer."
+ (buffer-local-value 'lsp-installation-buffer-mode buf))
+
+(defun lsp-select-installation-buffer (&optional show-finished)
+ "Interactively choose an installation buffer.
+If SHOW-FINISHED is set, leftover (finished) installation buffers
+are still shown."
+ (interactive "P")
+ (let ((bufs (--filter (and (lsp--installation-buffer? it)
+ (or show-finished (get-buffer-process it)))
+ (buffer-list))))
+ (pcase bufs
+ (`nil (user-error "No installation buffers"))
+ (`(,buf) (pop-to-buffer buf))
+ (bufs (pop-to-buffer (completing-read "Select installation buffer: "
+ (--map (propertize (buffer-name it) 'face
+ (if (get-buffer-process it)
+ 'lsp-installation-buffer-face
+ 'lsp-installation-finished-buffer-face))
+ bufs)))))))
+
+(defun lsp-cleanup-installation-buffers ()
+ "Delete finished *lsp-installation* buffers."
+ (interactive)
+ (dolist (buf (buffer-list))
+ (when (and (lsp--installation-buffer? buf) (not (get-buffer-process buf)))
+ (kill-buffer buf))))
+
+(defun lsp--download-status ()
+ (-some--> #'lsp--client-download-in-progress?
+ (lsp--filter-clients it)
+ (-map (-compose #'symbol-name #'lsp--client-server-id) it)
+ (format "%s" it)
+ (propertize it 'face 'success)
+ (format " Installing following servers: %s" it)
+ (propertize it
+ 'local-map (make-mode-line-mouse-map
+ 'mouse-1 #'lsp-select-installation-buffer)
+ 'mouse-face 'highlight)))
+
+(defun lsp--install-server-internal (client &optional update?)
+ (unless (lsp--client-download-server-fn client)
+ (user-error "There is no automatic installation for `%s', you have to install it manually following lsp-mode's documentation."
+ (lsp--client-server-id client)))
+
+ (setf (lsp--client-download-in-progress? client) t)
+ (add-to-list 'global-mode-string '(t (:eval (lsp--download-status))))
+ (cl-flet ((done
+ (success? &optional error-message)
+ ;; run with idle timer to make sure the lsp command is executed in
+ ;; the main thread, see #2739.
+ (run-with-timer
+ 0.0
+ nil
+ (lambda ()
+ (-let [(&lsp-cln 'server-id 'buffers) client]
+ (setf (lsp--client-download-in-progress? client) nil
+ (lsp--client-buffers client) nil)
+ (if success?
+ (lsp--info "Server %s downloaded, auto-starting in %s buffers." server-id
+ (length buffers))
+ (lsp--error "Server %s install process failed with the following error message: %s.
+Check `*lsp-install*' and `*lsp-log*' buffer."
+ server-id
+ error-message))
+ (seq-do
+ (lambda (buffer)
+ (when (lsp-buffer-live-p buffer)
+ (lsp-with-current-buffer buffer
+ (cl-callf2 -remove-item '(t (:eval (lsp--download-status)))
+ global-mode-string)
+ (when success? (lsp)))))
+ buffers)
+ (unless (lsp--filter-clients #'lsp--client-download-in-progress?)
+ (cl-callf2 -remove-item '(t (:eval (lsp--download-status)))
+ global-mode-string)))))))
+ (lsp--info "Download %s started." (lsp--client-server-id client))
+ (condition-case err
+ (funcall
+ (lsp--client-download-server-fn client)
+ client
+ (lambda () (done t))
+ (lambda (msg) (done nil msg))
+ update?)
+ (error
+ (done nil (error-message-string err))))))
+
+(defun lsp--require-packages ()
+ "Load `lsp-client-packages' if needed."
+ (when (and lsp-auto-configure (not lsp--client-packages-required))
+ (seq-do (lambda (package)
+ ;; loading client is slow and `lsp' can be called repeatedly
+ (unless (featurep package)
+ (require package nil t)))
+ lsp-client-packages)
+ (setq lsp--client-packages-required t)))
+
+;;;###autoload
+(defun lsp-install-server (update? &optional server-id)
+ "Interactively install server.
+When prefix UPDATE? is t force installation even if the server is present."
+ (interactive "P")
+ (lsp--require-packages)
+ (lsp--install-server-internal
+ (or (gethash server-id lsp-clients)
+ (lsp--completing-read
+ "Select server to install: "
+ (or (->> lsp-clients
+ (ht-values)
+ (-filter (-andfn
+ (-orfn (-not #'lsp--server-binary-present?)
+ (-const update?))
+ (-not #'lsp--client-download-in-progress?)
+ #'lsp--client-download-server-fn)))
+ (user-error "There are no servers with automatic installation"))
+ (-compose #'symbol-name #'lsp--client-server-id)
+ nil
+ t))
+ update?))
+
+;;;###autoload
+(defun lsp-ensure-server (server-id)
+ "Ensure server SERVER-ID"
+ (lsp--require-packages)
+ (if-let ((client (gethash server-id lsp-clients)))
+ (unless (lsp--server-binary-present? client)
+ (lsp--info "Server `%s' is not preset, installing..." server-id)
+ (lsp-install-server nil server-id))
+ (warn "Unable to find server registration with id %s" server-id)))
+
+(defun lsp-async-start-process (callback error-callback &rest command)
+ "Start async process COMMAND with CALLBACK and ERROR-CALLBACK."
+ (let ((name (cl-first command)))
+ (with-current-buffer (compilation-start (mapconcat #'shell-quote-argument command " ") t
+ (lambda (&rest _)
+ (generate-new-buffer-name (format "*lsp-install: %s*" name))))
+ (lsp-installation-buffer-mode +1)
+ (add-hook
+ 'compilation-finish-functions
+ (lambda (_buf status)
+ (if (string= "finished\n" status)
+ (condition-case err
+ (funcall callback)
+ (error
+ (funcall error-callback (error-message-string err))))
+ (funcall error-callback (s-trim-right status))))
+ nil t))))
+
+(defun lsp-resolve-value (value)
+ "Resolve VALUE's value.
+If it is function - call it.
+If it is symbol - return it's value
+Otherwise returns value itself."
+ (cond
+ ((functionp value) (funcall value))
+ ((symbolp value) (symbol-value value))
+ (value)))
+
+(defvar lsp-deps-providers
+ (list :npm (list :path #'lsp--npm-dependency-path
+ :install #'lsp--npm-dependency-install)
+ :system (list :path #'lsp--system-path)
+ :download (list :path #'lsp-download-path
+ :install #'lsp-download-install)))
+
+(defun lsp--system-path (path)
+ "If PATH is absolute and exists return it as is. Otherwise,
+return the absolute path to the executable defined by PATH or
+nil."
+ ;; For node.js 'sub-packages' PATH may point to a *.js file. Consider the
+ ;; typescript-language-server. When lsp invokes the server, lsp needs to
+ ;; supply the path to the typescript compiler, tsserver.js, as an argument. To
+ ;; make code platform independent, one must pass the absolute path to the
+ ;; tsserver.js file (Windows requires a *.js file - see help on the JavaScript
+ ;; child process spawn command that is invoked by the
+ ;; typescript-language-server). This is why we check for existence and not
+ ;; that the path is executable.
+ (let ((path (lsp-resolve-value path)))
+ (if (and (f-absolute? path)
+ (f-exists? path))
+ path
+ (executable-find path))))
+
+(defun lsp-package-path (dependency)
+ "Path to the DEPENDENCY each of the registered providers."
+ (let (path)
+ (-first (-lambda ((provider . rest))
+ (setq path (-some-> lsp-deps-providers
+ (plist-get provider)
+ (plist-get :path)
+ (apply rest))))
+ (gethash dependency lsp--dependencies))
+ path))
+
+(defun lsp-package-ensure (dependency callback error-callback)
+ "Asynchronously ensure a package."
+ (or (-first (-lambda ((provider . rest))
+ (-some-> lsp-deps-providers
+ (plist-get provider)
+ (plist-get :install)
+ (apply (cl-list* callback error-callback rest))))
+ (gethash dependency lsp--dependencies))
+ (funcall error-callback (format "Unable to find a way to install %s" dependency))))
+
+
+;; npm handling
+
+;; https://docs.npmjs.com/files/folders#executables
+(cl-defun lsp--npm-dependency-path (&key package path &allow-other-keys)
+ "Return npm dependency PATH for PACKAGE."
+ (let ((path (executable-find
+ (f-join lsp-server-install-dir "npm" package
+ (cond ((eq system-type 'windows-nt) "")
+ (t "bin"))
+ path))))
+ (unless (and path (f-exists? path))
+ (error "The package %s is not installed. Unable to find %s" package path))
+ path))
+
+(cl-defun lsp--npm-dependency-install (callback error-callback &key package &allow-other-keys)
+ (if-let ((npm-binary (executable-find "npm")))
+ (progn
+ ;; Explicitly `make-directory' to work around NPM bug in
+ ;; versions 7.0.0 through 7.4.1. See
+ ;; https://github.com/emacs-lsp/lsp-mode/issues/2364 for
+ ;; discussion.
+ (make-directory (f-join lsp-server-install-dir "npm" package "lib") 'parents)
+ (lsp-async-start-process callback
+ error-callback
+ npm-binary
+ "-g"
+ "--prefix"
+ (f-join lsp-server-install-dir "npm" package)
+ "install"
+ package))
+ (lsp-log "Unable to install %s via `npm' because it is not present" package)
+ nil))
+
+
+;; Download URL handling
+(cl-defun lsp-download-install (callback error-callback &key url asc-url pgp-key store-path decompress &allow-other-keys)
+ (let* ((url (lsp-resolve-value url))
+ (store-path (lsp-resolve-value store-path))
+ ;; (decompress (lsp-resolve-value decompress))
+ (download-path
+ (pcase decompress
+ (:gzip (concat store-path ".gz"))
+ (:zip (concat store-path ".zip"))
+ (`nil store-path)
+ (_ (error ":decompress must be `:gzip', `:zip' or `nil'")))))
+ (make-thread
+ (lambda ()
+ (condition-case err
+ (progn
+ (when (f-exists? download-path)
+ (f-delete download-path))
+ (when (f-exists? store-path)
+ (f-delete store-path))
+ (lsp--info "Starting to download %s to %s..." url download-path)
+ (mkdir (f-parent download-path) t)
+ (url-copy-file url download-path)
+ (lsp--info "Finished downloading %s..." download-path)
+ (when (and lsp-verify-signature asc-url pgp-key)
+ (if (executable-find epg-gpg-program)
+ (let ((asc-download-path (concat download-path ".asc"))
+ (context (epg-make-context))
+ (fingerprint)
+ (signature))
+ (when (f-exists? asc-download-path)
+ (f-delete asc-download-path))
+ (lsp--info "Starting to download %s to %s..." asc-url asc-download-path)
+ (url-copy-file asc-url asc-download-path)
+ (lsp--info "Finished downloading %s..." asc-download-path)
+ (epg-import-keys-from-string context pgp-key)
+ (setq fingerprint (epg-import-status-fingerprint
+ (car
+ (epg-import-result-imports
+ (epg-context-result-for context 'import)))))
+ (lsp--info "Verifying signature %s..." asc-download-path)
+ (epg-verify-file context asc-download-path download-path)
+ (setq signature (car (epg-context-result-for context 'verify)))
+ (unless (and
+ (eq (epg-signature-status signature) 'good)
+ (equal (epg-signature-fingerprint signature) fingerprint))
+ (error "Failed to verify GPG signature: %s" (epg-signature-to-string signature))))
+ (lsp--warn "GPG is not installed, skipping the signature check.")))
+ (when decompress
+ (lsp--info "Decompressing %s..." download-path)
+ (pcase decompress
+ (:gzip
+ (lsp-gunzip download-path))
+ (:zip (lsp-unzip download-path (f-parent store-path))))
+ (lsp--info "Decompressed %s..." store-path))
+ (funcall callback))
+ (error (funcall error-callback err)))))))
+
+(cl-defun lsp-download-path (&key store-path binary-path set-executable? &allow-other-keys)
+ "Download URL and store it into STORE-PATH.
+
+SET-EXECUTABLE? when non-nil change the executable flags of
+STORE-PATH to make it executable. BINARY-PATH can be specified
+when the binary to start does not match the name of the
+archieve(e. g. when the archieve has multiple files)"
+ (let ((store-path (or (lsp-resolve-value binary-path)
+ (lsp-resolve-value store-path))))
+ (cond
+ ((executable-find store-path) store-path)
+ ((and set-executable? (f-exists? store-path))
+ (set-file-modes store-path #o0700)
+ store-path)
+ ((f-exists? store-path) store-path))))
+
+;; unzip
+
+(defconst lsp-ext-pwsh-script "powershell -noprofile -noninteractive \
+-nologo -ex bypass Expand-Archive -path '%s' -dest '%s'"
+ "Powershell script to unzip file.")
+
+(defconst lsp-ext-unzip-script "bash -c 'mkdir -p %2$s && unzip -qq -o %1$s -d %2$s'"
+ "Unzip script to unzip file.")
+
+(defcustom lsp-unzip-script (cond ((executable-find "powershell") lsp-ext-pwsh-script)
+ ((executable-find "unzip") lsp-ext-unzip-script)
+ (t nil))
+ "The script to unzip."
+ :group 'lsp-mode
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-unzip (zip-file dest)
+ "Unzip ZIP-FILE to DEST."
+ (unless lsp-unzip-script
+ (error "Unable to find `unzip' or `powershell' on the path, please customize `lsp-unzip-script'"))
+ (shell-command (format lsp-unzip-script zip-file dest)))
+
+;; gunzip
+
+(defconst lsp-ext-gunzip-script "gzip -d %1$s"
+ "Script to decompress a gzippped file with gzip.")
+
+(defcustom lsp-gunzip-script (cond ((executable-find "gzip") lsp-ext-gunzip-script)
+ (t nil))
+ "The script to decompress a gzipped file.
+Should be a format string with one argument for the file to be decompressed
+in place."
+ :group 'lsp-mode
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-gunzip (gz-file)
+ "Decompress GZ-FILE in place."
+ (unless lsp-gunzip-script
+ (error "Unable to find `gzip' on the path, please either customize `lsp-gunzip-script' or manually decompress %s" gz-file))
+ (shell-command (format lsp-gunzip-script gz-file)))
+
+;; VSCode marketplace
+
+(defcustom lsp-vscode-ext-url
+ "https://marketplace.visualstudio.com/_apis/public/gallery/publishers/%s/vsextensions/%s/%s/vspackage"
+ "Vscode extension template url."
+ :group 'lsp-mode
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-vscode-extension-url (publisher name &optional version)
+ "Return the URL to vscode extension.
+PUBLISHER is the extension publisher.
+NAME is the name of the extension.
+VERSION is the version of the extension, defaults to `latest'"
+ (format lsp-vscode-ext-url publisher name (or version "latest")))
+
+
+
+;; Queueing prompts
+
+(defvar lsp--question-queue nil
+ "List of questions yet to be asked by `lsp-ask-question'.")
+
+(defun lsp-ask-question (question options callback)
+ "Prompt the user to answer the QUESTION with one of the OPTIONS from the
+minibuffer. Once the user selects an option, the CALLBACK function will be
+called, passing the selected option to it.
+
+If the user is currently being shown a question, the question will be stored in
+`lsp--question-queue', and will be asked once the user has answered the current
+question."
+ (add-to-list 'lsp--question-queue `(("question" . ,question)
+ ("options" . ,options)
+ ("callback" . ,callback)) t)
+ (when (eq (length lsp--question-queue) 1)
+ (lsp--process-question-queue)))
+
+(defun lsp--process-question-queue ()
+ "Take the first question from `lsp--question-queue', process it, then process
+the next question until the queue is empty."
+ (-let* (((&alist "question" "options" "callback") (car lsp--question-queue))
+ (answer (completing-read question options nil t)))
+ (pop lsp--question-queue)
+ (funcall callback answer)
+ (when lsp--question-queue
+ (lsp--process-question-queue))))
+
+(defun lsp--matching-clients? (client)
+ (and
+ ;; both file and client remote or both local
+ (eq (---truthy? (file-remote-p (buffer-file-name)))
+ (---truthy? (lsp--client-remote? client)))
+
+ ;; activation function or major-mode match.
+ (if-let ((activation-fn (lsp--client-activation-fn client)))
+ (funcall activation-fn (buffer-file-name) major-mode)
+ (-contains? (lsp--client-major-modes client) major-mode))
+
+ ;; check whether it is enabled if `lsp-enabled-clients' is not null
+ (or (null lsp-enabled-clients)
+ (or (member (lsp--client-server-id client) lsp-enabled-clients)
+ (ignore (lsp--info "Client %s is not in lsp-enabled-clients"
+ (lsp--client-server-id client)))))
+
+ ;; check whether it is not disabled.
+ (not (lsp--client-disabled-p major-mode (lsp--client-server-id client)))))
+
+(defun lsp--filter-clients (pred)
+ (->> lsp-clients hash-table-values (-filter pred)))
+
+(defun lsp--find-clients ()
+ "Find clients which can handle BUFFER-MAJOR-MODE.
+SESSION is the currently active session. The function will also
+pick only remote enabled clients in case the FILE-NAME is on
+remote machine and vice versa."
+ (-when-let (matching-clients (lsp--filter-clients (-andfn #'lsp--matching-clients?
+ #'lsp--server-binary-present?)))
+ (lsp-log "Found the following clients for %s: %s"
+ (buffer-file-name)
+ (s-join ", "
+ (-map (lambda (client)
+ (format "(server-id %s, priority %s)"
+ (lsp--client-server-id client)
+ (lsp--client-priority client)))
+ matching-clients)))
+ (-let* (((add-on-clients main-clients) (-separate #'lsp--client-add-on? matching-clients))
+ (selected-clients (if-let ((main-client (and main-clients
+ (--max-by (> (lsp--client-priority it)
+ (lsp--client-priority other))
+ main-clients))))
+ (cons main-client add-on-clients)
+ add-on-clients)))
+ (lsp-log "The following clients were selected based on priority: %s"
+ (s-join ", "
+ (-map (lambda (client)
+ (format "(server-id %s, priority %s)"
+ (lsp--client-server-id client)
+ (lsp--client-priority client)))
+ selected-clients)))
+ selected-clients)))
+
+(defun lsp-register-client (client)
+ "Registers LSP client CLIENT."
+ (cl-assert (symbolp (lsp--client-server-id client)) t)
+ (cl-assert (or
+ (functionp (lsp--client-activation-fn client))
+ (and (listp (lsp--client-major-modes client))
+ (seq-every-p (apply-partially #'symbolp)
+ (lsp--client-major-modes client))))
+ nil "Invalid activation-fn and/or major-modes.")
+ (let ((client-id (lsp--client-server-id client)))
+ (puthash client-id client lsp-clients)
+ (setplist (intern (format "lsp-%s-after-open-hook" client-id))
+ `( standard-value (nil) custom-type hook
+ custom-package-version (lsp-mode . "7.0.1")
+ variable-documentation ,(format "Hooks to run after `%s' server is run." client-id)
+ custom-requests nil))))
+
+(defun lsp--create-initialization-options (_session client)
+ "Create initialization-options from SESSION and CLIENT.
+Add workspace folders depending on server being multiroot and
+session workspace folder configuration for the server."
+ (let* ((initialization-options-or-fn (lsp--client-initialization-options client)))
+ (if (functionp initialization-options-or-fn)
+ (funcall initialization-options-or-fn)
+ initialization-options-or-fn)))
+
+(defvar lsp-client-settings nil
+ "For internal use, any external users please use
+ `lsp-register-custom-settings' function instead")
+
+(defun lsp--compare-setting-path (a b)
+ (equal (car a) (car b)))
+
+(defun lsp-register-custom-settings (props)
+ "Register PROPS.
+PROPS is list of triple (path value boolean?) where PATH is the path to the
+property; VALUE can be a literal value, symbol to be evaluated, or either a
+function or lambda function to be called without arguments; BOOLEAN? is an
+optional flag that should be non-nil for boolean settings, when it is nil the
+property will be ignored if the VALUE is nil.
+
+Example: `(lsp-register-custom-settings '((\"foo.bar.buzz.enabled\" t t)))'
+\(note the double parentheses)"
+ (let ((-compare-fn #'lsp--compare-setting-path))
+ (setq lsp-client-settings (-uniq (append props lsp-client-settings)))))
+
+(defun lsp-region-text (region)
+ "Get the text for REGION in current buffer."
+ (-let (((start . end) (lsp--range-to-region region)))
+ (buffer-substring-no-properties start end)))
+
+(defun lsp-ht-set (tbl paths value)
+ "Set nested hash table value.
+TBL - a hash table, PATHS is the path to the nested VALUE."
+ (pcase paths
+ (`(,path) (ht-set! tbl path value))
+ (`(,path . ,rst) (let ((nested-tbl (or (gethash path tbl)
+ (let ((temp-tbl (ht)))
+ (ht-set! tbl path temp-tbl)
+ temp-tbl))))
+ (lsp-ht-set nested-tbl rst value)))))
+
+(defun lsp-configuration-section (section)
+ "Get settings for SECTION."
+ (let ((ret (ht-create)))
+ (mapc (-lambda ((path variable boolean?))
+ (when (s-matches? (concat (regexp-quote section) "\\..*") path)
+ (let* ((symbol-value (-> variable
+ lsp-resolve-value
+ lsp-resolve-value))
+ (value (if (and boolean? (not symbol-value))
+ :json-false
+ symbol-value)))
+ (when (or boolean? value)
+ (lsp-ht-set ret (s-split "\\." path) value)))))
+ lsp-client-settings)
+ ret))
+
+(defun lsp--start-connection (session client project-root)
+ "Initiates connection created from CLIENT for PROJECT-ROOT.
+SESSION is the active session."
+ (when (lsp--client-multi-root client)
+ (cl-pushnew project-root (gethash (lsp--client-server-id client)
+ (lsp-session-server-id->folders session))))
+ (run-hook-with-args 'lsp-workspace-folders-changed-functions (list project-root) nil)
+
+ (unwind-protect
+ (lsp--start-workspace session client project-root (lsp--create-initialization-options session client))
+ (lsp--spinner-stop)))
+
+;; lsp-log-io-mode
+
+(defvar lsp-log-io-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "M-n") #'lsp-log-io-next)
+ (define-key map (kbd "M-p") #'lsp-log-io-prev)
+ (define-key map (kbd "k") #'lsp--erase-log-buffer)
+ (define-key map (kbd "K") #'lsp--erase-session-log-buffers)
+ map)
+ "Keymap for lsp log buffer mode.")
+
+(define-derived-mode lsp-log-io-mode special-mode "LspLogIo"
+ "Special mode for viewing IO logs.")
+
+(defun lsp-workspace-show-log (workspace)
+ "Display the log buffer of WORKSPACE."
+ (interactive
+ (list (if lsp-print-io
+ (if (eq (length (lsp-workspaces)) 1)
+ (cl-first (lsp-workspaces))
+ (lsp--completing-read "Workspace: " (lsp-workspaces)
+ #'lsp--workspace-print nil t))
+ (user-error "IO logging is disabled"))))
+ (pop-to-buffer (lsp--get-log-buffer-create workspace)))
+
+(defalias 'lsp-switch-to-io-log-buffer 'lsp-workspace-show-log)
+
+(defun lsp--get-log-buffer-create (workspace)
+ "Return the lsp log buffer of WORKSPACE, creating a new one if needed."
+ (let ((server-id (-> workspace lsp--workspace-client lsp--client-server-id symbol-name))
+ (pid (format "%s" (process-id (lsp--workspace-cmd-proc workspace)))))
+ (get-buffer-create (format "*lsp-log: %s:%s*" server-id pid))))
+
+(defun lsp--erase-log-buffer (&optional all)
+ "Delete contents of current lsp log buffer.
+When ALL is t, erase all log buffers of the running session."
+ (interactive)
+ (let* ((workspaces (lsp--session-workspaces (lsp-session)))
+ (current-log-buffer (current-buffer)))
+ (dolist (w workspaces)
+ (let ((b (lsp--get-log-buffer-create w)))
+ (when (or all (eq b current-log-buffer))
+ (with-current-buffer b
+ (let ((inhibit-read-only t))
+ (erase-buffer))))))))
+
+(defun lsp--erase-session-log-buffers ()
+ "Erase log buffers of the running session."
+ (interactive)
+ (lsp--erase-log-buffer t))
+
+(defun lsp-log-io-next (arg)
+ "Move to next log entry."
+ (interactive "P")
+ (ewoc-goto-next lsp--log-io-ewoc (or arg 1)))
+
+(defun lsp-log-io-prev (arg)
+ "Move to previous log entry."
+ (interactive "P")
+ (ewoc-goto-prev lsp--log-io-ewoc (or arg 1)))
+
+(defun lsp--workspace-print (workspace)
+ "Visual representation WORKSPACE."
+ (let* ((proc (lsp--workspace-cmd-proc workspace))
+ (status (lsp--workspace-status workspace))
+ (server-id (-> workspace lsp--workspace-client lsp--client-server-id symbol-name))
+ (pid (process-id proc)))
+
+ (if (eq 'initialized status)
+ (format "%s:%s" server-id pid)
+ (format "%s:%s/%s" server-id pid status))))
+
+(defun lsp--map-tree-widget (m)
+ "Build `tree-widget' from a hash-table M."
+ (when (hash-table-p m)
+ (let (nodes)
+ (maphash (lambda (k v)
+ (push `(tree-widget
+ :tag ,(if (hash-table-p v)
+ (format "%s:" k)
+ (format "%s: %s" k
+ (propertize (format "%s" v)
+ 'face
+ 'font-lock-string-face)))
+ :open t
+ ,@(lsp--map-tree-widget v))
+ nodes))
+ m)
+ nodes)))
+
+(defun lsp-buffer-name (buffer-id)
+ (if-let ((buffer-name (plist-get buffer-id :buffer-name)))
+ (funcall buffer-name buffer-id)
+ (buffer-name buffer-id)))
+
+(defun lsp--render-workspace (workspace)
+ "Tree node representation of WORKSPACE."
+ `(tree-widget :tag ,(lsp--workspace-print workspace)
+ :open t
+ (tree-widget :tag ,(propertize "Buffers" 'face 'font-lock-function-name-face)
+ :open t
+ ,@(->> workspace
+ (lsp--workspace-buffers)
+ (--map `(tree-widget
+ :tag ,(when (lsp-buffer-live-p it)
+ (let ((buffer-name (lsp-buffer-name it)))
+ (if (lsp-with-current-buffer it buffer-read-only)
+ (propertize buffer-name 'face 'font-lock-constant-face)
+ buffer-name)))))))
+ (tree-widget :tag ,(propertize "Capabilities" 'face 'font-lock-function-name-face)
+ ,@(-> workspace lsp--workspace-server-capabilities lsp--map-tree-widget))))
+
+(define-derived-mode lsp-browser-mode special-mode "LspBrowser"
+ "Define mode for displaying lsp sessions."
+ (setq-local display-buffer-base-action '(nil . ((inhibit-same-window . t)))))
+
+(defun lsp-describe-session ()
+ "Describes current `lsp-session'."
+ (interactive)
+ (let ((session (lsp-session))
+ (buf (get-buffer-create "*lsp session*")))
+ (with-current-buffer buf
+ (lsp-browser-mode)
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (--each (lsp-session-folders session)
+ (widget-create
+ `(tree-widget
+ :tag ,(propertize it 'face 'font-lock-keyword-face)
+ :open t
+ ,@(->> session
+ (lsp-session-folder->servers)
+ (gethash it)
+ (-map 'lsp--render-workspace)))))))
+ (pop-to-buffer buf)))
+
+(defun lsp--session-workspaces (session)
+ "Get all workspaces that are part of the SESSION."
+ (-> session lsp-session-folder->servers hash-table-values -flatten -uniq))
+
+(defun lsp--find-multiroot-workspace (session client project-root)
+ "Look for a multiroot connection in SESSION created from CLIENT for PROJECT-ROOT and BUFFER-MAJOR-MODE."
+ (when (lsp--client-multi-root client)
+ (-when-let (multi-root-workspace (->> session
+ (lsp--session-workspaces)
+ (--first (eq (-> it lsp--workspace-client lsp--client-server-id)
+ (lsp--client-server-id client)))))
+ (with-lsp-workspace multi-root-workspace
+ (lsp-notify "workspace/didChangeWorkspaceFolders"
+ (lsp-make-did-change-workspace-folders-params
+ :event (lsp-make-workspace-folders-change-event
+ :added (vector (lsp-make-workspace-folder
+ :uri (lsp--path-to-uri project-root)
+ :name (f-filename project-root)))
+ :removed []))))
+
+ (->> session (lsp-session-folder->servers) (gethash project-root) (cl-pushnew multi-root-workspace))
+ (->> session (lsp-session-server-id->folders) (gethash (lsp--client-server-id client)) (cl-pushnew project-root))
+
+ (lsp--persist-session session)
+
+ (lsp--info "Opened folder %s in workspace %s" project-root (lsp--workspace-print multi-root-workspace))
+ (lsp--open-in-workspace multi-root-workspace)
+
+ multi-root-workspace)))
+
+(defun lsp--ensure-lsp-servers (session clients project-root ignore-multi-folder)
+ "Ensure that SESSION contain server CLIENTS created for PROJECT-ROOT.
+IGNORE-MULTI-FOLDER to ignore multi folder server."
+ (-map (lambda (client)
+ (or
+ (lsp--find-workspace session client project-root)
+ (unless ignore-multi-folder
+ (lsp--find-multiroot-workspace session client project-root))
+ (lsp--start-connection session client project-root)))
+ clients))
+
+(defun lsp--spinner-stop ()
+ "Stop the spinner in case all of the workspaces are started."
+ (when (--all? (eq (lsp--workspace-status it) 'initialized)
+ lsp--buffer-workspaces)
+ (spinner-stop)))
+
+(defun lsp--open-in-workspace (workspace)
+ "Open in existing WORKSPACE."
+ (if (eq 'initialized (lsp--workspace-status workspace))
+ ;; when workspace is initialized just call document did open.
+ (progn
+ (with-lsp-workspace workspace
+ (when-let ((before-document-open-fn (-> workspace
+ lsp--workspace-client
+ lsp--client-before-file-open-fn)))
+ (funcall before-document-open-fn workspace))
+ (lsp--text-document-did-open))
+ (lsp--spinner-stop))
+ ;; when it is not initialized
+ (lsp--spinner-start)
+ (cl-pushnew (lsp-current-buffer) (lsp--workspace-buffers workspace))))
+
+(defun lsp--find-workspace (session client project-root)
+ "Find server connection created with CLIENT in SESSION for PROJECT-ROOT."
+ (when-let ((workspace (->> session
+ (lsp-session-folder->servers)
+ (gethash project-root)
+ (--first (eql (-> it lsp--workspace-client lsp--client-server-id)
+ (lsp--client-server-id client))))))
+ (lsp--open-in-workspace workspace)
+ workspace))
+
+(defun lsp--find-root-interactively (session)
+ "Find project interactively.
+Returns nil if the project should not be added to the current SESSION."
+ (condition-case nil
+ (let* ((project-root-suggestion (or (lsp--suggest-project-root) default-directory))
+ (action (read-key (format
+ "%s is not part of any project. Select action:
+
+%s==>Import project root %s.
+%s==>Import project by selecting root directory interactively.
+%s==>Do not ask again for the current project by adding %s to lsp-session-folders-blacklist.
+%s==>Do not ask again for the current project by selecting ignore path interactively.
+%s==>Do nothing: ask again when opening other files from the current project."
+ (propertize (buffer-name) 'face 'bold)
+ (propertize "i" 'face 'success)
+ (propertize project-root-suggestion 'face 'bold)
+ (propertize "I" 'face 'success)
+ (propertize "d" 'face 'warning)
+ (propertize project-root-suggestion 'face 'bold)
+ (propertize "D" 'face 'warning)
+ (propertize "n" 'face 'warning)))))
+ (cl-case action
+ (?i project-root-suggestion)
+ (?\r project-root-suggestion)
+ (?I (read-directory-name "Select workspace folder to add: "
+ (or project-root-suggestion default-directory)
+ nil
+ t))
+ (?d (push project-root-suggestion (lsp-session-folders-blacklist session))
+ (lsp--persist-session session)
+ nil)
+ (?D (push (read-directory-name "Select folder to blacklist: "
+ (or project-root-suggestion default-directory)
+ nil
+ t)
+ (lsp-session-folders-blacklist session))
+ (lsp--persist-session session)
+ nil)
+ (t nil)))
+ ('quit)))
+
+(declare-function tramp-file-name-host "ext:tramp" (file) t)
+(declare-function tramp-dissect-file-name "ext:tramp" (file &optional nodefault))
+
+(defun lsp--files-same-host (f1 f2)
+ "Predicate on whether or not two files are on the same host."
+ (or (not (or (file-remote-p f1) (file-remote-p f2)))
+ (and (file-remote-p f1)
+ (file-remote-p f2)
+ (progn (require 'tramp)
+ (equal (tramp-file-name-host (tramp-dissect-file-name f1))
+ (tramp-file-name-host (tramp-dissect-file-name f2)))))))
+
+(defun lsp-find-session-folder (session file-name)
+ "Look in the current SESSION for folder containing FILE-NAME."
+ (let ((file-name-canonical (lsp-f-canonical file-name)))
+ (->> session
+ (lsp-session-folders)
+ (--filter (and (lsp--files-same-host it file-name-canonical)
+ (or (lsp-f-same? it file-name-canonical)
+ (and (f-dir? it)
+ (lsp-f-ancestor-of? it file-name-canonical)))))
+ (--max-by (> (length it)
+ (length other))))))
+
+(defun lsp-find-workspace (server-id &optional file-name)
+ "Find workspace for SERVER-ID for FILE-NAME."
+ (-when-let* ((session (lsp-session))
+ (folder->servers (lsp-session-folder->servers session))
+ (workspaces (if file-name
+ (gethash (lsp-find-session-folder session file-name) folder->servers)
+ (lsp--session-workspaces session))))
+
+ (--first (eq (lsp--client-server-id (lsp--workspace-client it)) server-id) workspaces)))
+
+(defun lsp--calculate-root (session file-name)
+ "Calculate project root for FILE-NAME in SESSION."
+ (and
+ (->> session
+ (lsp-session-folders-blacklist)
+ (--first (and (lsp--files-same-host it file-name)
+ (lsp-f-ancestor-of? it file-name)
+ (prog1 t
+ (lsp--info "File %s is in blacklisted directory %s" file-name it))))
+ not)
+ (or
+ (when lsp-auto-guess-root
+ (lsp--suggest-project-root))
+ (lsp-find-session-folder session file-name)
+ (unless lsp-auto-guess-root
+ (lsp--find-root-interactively session)))))
+
+(defun lsp--try-open-in-library-workspace ()
+ "Try opening current file as library file in any of the active workspace.
+The library folders are defined by each client for each of the active workspace."
+ (when-let ((workspace (->> (lsp-session)
+ (lsp--session-workspaces)
+ ;; Sort the last active workspaces first as they are more likely to be
+ ;; the correct ones, especially when jumping to a definition.
+ (-sort (lambda (a _b)
+ (-contains? lsp--last-active-workspaces a)))
+ (--first
+ (and (-> it lsp--workspace-client lsp--matching-clients?)
+ (when-let ((library-folders-fn
+ (-> it lsp--workspace-client lsp--client-library-folders-fn)))
+ (-first (lambda (library-folder)
+ (lsp-f-ancestor-of? library-folder (buffer-file-name)))
+ (funcall library-folders-fn it))))))))
+ (lsp--open-in-workspace workspace)
+ (view-mode t)
+ (lsp--info "Opening read-only library file %s." (buffer-file-name))
+ (list workspace)))
+
+(defun lsp--persist-session (session)
+ "Persist SESSION to `lsp-session-file'."
+ (lsp--persist lsp-session-file (make-lsp-session
+ :folders (lsp-session-folders session)
+ :folders-blacklist (lsp-session-folders-blacklist session)
+ :server-id->folders (lsp-session-server-id->folders session))))
+
+(defun lsp--try-project-root-workspaces (ask-for-client ignore-multi-folder)
+ "Try create opening file as a project file.
+When IGNORE-MULTI-FOLDER is t the lsp mode will start new
+language server even if there is language server which can handle
+current language. When IGNORE-MULTI-FOLDER is nil current file
+will be opened in multi folder language server if there is
+such."
+ (-let ((session (lsp-session)))
+ (-if-let (clients (if ask-for-client
+ (list (lsp--completing-read "Select server to start: "
+ (ht-values lsp-clients)
+ (-compose 'symbol-name 'lsp--client-server-id) nil t))
+ (lsp--find-clients)))
+ (-if-let (project-root (-some-> session
+ (lsp--calculate-root (buffer-file-name))
+ (lsp-f-canonical)))
+ (progn
+ ;; update project roots if needed and persist the lsp session
+ (unless (-contains? (lsp-session-folders session) project-root)
+ (cl-pushnew project-root (lsp-session-folders session))
+ (lsp--persist-session session))
+ (lsp--ensure-lsp-servers session clients project-root ignore-multi-folder))
+ (lsp--warn "%s not in project or it is blacklisted." (buffer-name))
+ nil)
+ (lsp--warn "No LSP server for %s(check *lsp-log*)." major-mode)
+ nil)))
+
+(defun lsp-shutdown-workspace ()
+ "Shutdown language server."
+ (interactive)
+ (--when-let (pcase (lsp-workspaces)
+ (`nil (user-error "There are no active servers in the current buffer"))
+ (`(,workspace) (when (y-or-n-p (format "Are you sure you want to stop the server %s?"
+ (lsp--workspace-print workspace)))
+ workspace))
+ (workspaces (lsp--completing-read "Select server: "
+ workspaces
+ 'lsp--workspace-print nil t)))
+ (lsp-workspace-shutdown it)))
+
+(make-obsolete 'lsp-shutdown-workspace 'lsp-workspace-shutdown "lsp-mode 6.1")
+
+(defcustom lsp-auto-select-workspace t
+ "Shutdown or restart a single workspace.
+If set and the current buffer has only a single workspace
+associated with it, `lsp-shutdown-workspace' and
+`lsp-restart-workspace' will act on it without asking."
+ :type 'boolean
+ :group 'lsp-mode)
+
+(defun lsp--read-workspace ()
+ "Ask the user to select a workspace.
+Errors if there are none."
+ (pcase (lsp-workspaces)
+ (`nil (error "No workspaces associated with the current buffer"))
+ ((and `(,workspace) (guard lsp-auto-select-workspace)) workspace)
+ (workspaces (lsp--completing-read "Select workspace: " workspaces
+ #'lsp--workspace-print nil t))))
+
+(defun lsp-workspace-shutdown (workspace)
+ "Shut the workspace WORKSPACE and the language server associated with it"
+ (interactive (list (lsp--read-workspace)))
+ (lsp--warn "Stopping %s" (lsp--workspace-print workspace))
+ (with-lsp-workspace workspace (lsp--shutdown-workspace)))
+
+(defun lsp-disconnect ()
+ "Disconnect the buffer from the language server."
+ (interactive)
+ (lsp--text-document-did-close t)
+ (lsp-managed-mode -1)
+ (lsp-mode -1)
+ (setq lsp--buffer-workspaces nil)
+ (lsp--info "Disconnected"))
+
+(defun lsp-restart-workspace ()
+ (interactive)
+ (--when-let (pcase (lsp-workspaces)
+ (`nil (user-error "There are no active servers in the current buffer"))
+ (`(,workspace) workspace)
+ (workspaces (lsp--completing-read "Select server: "
+ workspaces
+ 'lsp--workspace-print nil t)))
+ (lsp-workspace-restart it)))
+
+(make-obsolete 'lsp-restart-workspace 'lsp-workspace-restart "lsp-mode 6.1")
+
+(defun lsp-workspace-restart (workspace)
+ "Restart the workspace WORKSPACE and the language server associated with it"
+ (interactive (list (lsp--read-workspace)))
+ (lsp--warn "Restarting %s" (lsp--workspace-print workspace))
+ (with-lsp-workspace workspace (lsp--shutdown-workspace t)))
+
+;;;###autoload
+(defun lsp (&optional arg)
+ "Entry point for the server startup.
+When ARG is t the lsp mode will start new language server even if
+there is language server which can handle current language. When
+ARG is nil current file will be opened in multi folder language
+server if there is such. When `lsp' is called with prefix
+argument ask the user to select which language server to start."
+ (interactive "P")
+
+ (lsp--require-packages)
+
+ (when (buffer-file-name)
+ (let (clients
+ (matching-clients (lsp--filter-clients
+ (-andfn #'lsp--matching-clients?
+ #'lsp--server-binary-present?))))
+ (cond
+ (matching-clients
+ (when (setq lsp--buffer-workspaces
+ (or (and
+ ;; Don't open as library file if file is part of a project.
+ (not (lsp-find-session-folder (lsp-session) (buffer-file-name)))
+ (lsp--try-open-in-library-workspace))
+ (lsp--try-project-root-workspaces (equal arg '(4))
+ (and arg (not (equal arg 1))))))
+ (lsp-mode 1)
+ (when lsp-auto-configure (lsp--auto-configure))
+ (setq lsp-buffer-uri (lsp--buffer-uri))
+ (lsp--info "Connected to %s."
+ (apply 'concat (--map (format "[%s]" (lsp--workspace-print it))
+ lsp--buffer-workspaces)))))
+ ;; look for servers which are currently being downloaded.
+ ((setq clients (lsp--filter-clients (-andfn #'lsp--matching-clients?
+ #'lsp--client-download-in-progress?)))
+ (lsp--info "There are language server(%s) installation in progress.
+The server(s) will be started in the buffer when it has finished."
+ (-map #'lsp--client-server-id clients))
+ (seq-do (lambda (client)
+ (cl-pushnew (current-buffer) (lsp--client-buffers client)))
+ clients))
+ ;; look for servers to install
+ ((setq clients (lsp--filter-clients (-andfn #'lsp--matching-clients?
+ #'lsp--client-download-server-fn
+ (-not #'lsp--client-download-in-progress?))))
+ (let ((client (lsp--completing-read
+ (concat "Unable to find installed server supporting this file. "
+ "The following servers could be installed automatically: ")
+ clients
+ (-compose #'symbol-name #'lsp--client-server-id)
+ nil
+ t)))
+ (cl-pushnew (current-buffer) (lsp--client-buffers client))
+ (lsp--install-server-internal client)))
+ ;; no clients present
+ ((setq clients (unless matching-clients
+ (lsp--filter-clients (-andfn #'lsp--matching-clients?
+ (-not #'lsp--server-binary-present?)))))
+ (lsp--warn "The following servers support current file but do not have automatic installation configuration: %s
+You may find the installation instructions at https://emacs-lsp.github.io/lsp-mode/page/languages.
+\(If you have already installed the server check *lsp-log*)."
+ (mapconcat (lambda (client)
+ (symbol-name (lsp--client-server-id client)))
+ clients
+ " ")))
+ ;; no matches
+ ((-> #'lsp--matching-clients? lsp--filter-clients not)
+ (lsp--error "There are no language servers supporting current mode `%s' registered with `lsp-mode'.
+This issue might be caused by:
+1. The language you are trying to use does not have built-in support in `lsp-mode'. You must install the required support manually. Examples of this are `lsp-java' or `lsp-metals'.
+2. The language server that you expect to run is not configured to run for major mode `%s'. You may check that by checking the `:major-modes' that are passed to `lsp-register-client'.
+3. `lsp-mode' doesn't have any integration for the language behind `%s'. Refer to https://emacs-lsp.github.io/lsp-mode/page/languages and https://langserver.org/ .
+4. You are over `tramp'. In this case follow https://emacs-lsp.github.io/lsp-mode/page/remote/.
+5. You have disabled the `lsp-mode' clients for that file. (Check `lsp-enabled-clients' and `lsp-disabled-clients')."
+ major-mode major-mode major-mode))))))
+
+(defun lsp--init-if-visible ()
+ "Run `lsp' for the current buffer if the buffer is visible.
+Returns `t' if `lsp' was run for the buffer."
+ (when (or (buffer-modified-p) (get-buffer-window nil t))
+ (remove-hook 'window-configuration-change-hook #'lsp--init-if-visible t)
+ (lsp)
+ t))
+
+;;;###autoload
+(defun lsp-deferred ()
+ "Entry point that defers server startup until buffer is visible.
+`lsp-deferred' will wait until the buffer is visible before invoking `lsp'.
+This avoids overloading the server with many files when starting Emacs."
+ ;; Workspace may not be initialized yet. Use a buffer local variable to
+ ;; remember that we deferred loading of this buffer.
+ (setq lsp--buffer-deferred t)
+ (let ((buffer (current-buffer)))
+ ;; Avoid false positives as desktop-mode restores buffers by deferring
+ ;; visibility check until the stack clears.
+ (run-with-timer 0 nil (lambda ()
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (unless (lsp--init-if-visible)
+ (add-hook 'window-configuration-change-hook #'lsp--init-if-visible nil t))))))))
+
+
+
+(defvar lsp-file-truename-cache (ht))
+
+(defmacro lsp-with-cached-filetrue-name (&rest body)
+ "Executes BODY caching the `file-truename' calls."
+ `(let ((old-fn (symbol-function 'file-truename)))
+ (unwind-protect
+ (progn
+ (fset 'file-truename
+ (lambda (file-name &optional counter prev-dirs)
+ (or (gethash file-name lsp-file-truename-cache)
+ (puthash file-name (apply old-fn (list file-name counter prev-dirs))
+ lsp-file-truename-cache))))
+ ,@body)
+ (fset 'file-truename old-fn))))
+
+
+(defun lsp-virtual-buffer-call (key &rest args)
+ (when lsp--virtual-buffer
+ (when-let ((fn (plist-get lsp--virtual-buffer key)))
+ (apply fn args))))
+
+(defun lsp-translate-column (column)
+ "Translate COLUMN taking into account virtual buffers."
+ (or (lsp-virtual-buffer-call :real->virtual-char column)
+ column))
+
+(defun lsp-translate-line (line)
+ "Translate LINE taking into account virtual buffers."
+ (or (lsp-virtual-buffer-call :real->virtual-line line)
+ line))
+
+
+;; lsp internal validation.
+
+(defmacro lsp--doctor (&rest checks)
+ `(-let [buf (current-buffer)]
+ (with-current-buffer (get-buffer-create "*lsp-performance*")
+ (with-help-window (current-buffer)
+ ,@(-map (-lambda ((msg form))
+ `(insert (format "%s: %s\n" ,msg
+ (let ((res (with-current-buffer buf
+ ,form)))
+ (cond
+ ((eq res :optional) (propertize "NOT AVAILABLE (OPTIONAL)" 'face 'warning))
+ (res (propertize "OK" 'face 'success))
+ (t (propertize "ERROR" 'face 'error)))))))
+ (-partition 2 checks))))))
+
+(define-obsolete-function-alias 'lsp-diagnose
+ 'lsp-doctor "lsp-mode 7.1")
+
+(defun lsp-doctor ()
+ "Validate performance settings."
+ (interactive)
+ (lsp--doctor
+ "Checking for Native JSON support" (functionp 'json-serialize)
+ "Check emacs supports `read-process-output-max'" (boundp 'read-process-output-max)
+ "Check `read-process-output-max' default has been changed from 4k"
+ (and (boundp 'read-process-output-max)
+ (> read-process-output-max 4096))
+ "Byte compiled against Native JSON (recompile lsp-mode if failing when Native JSON available)"
+ (condition-case _err
+ (progn (lsp--make-message (list "a" "b"))
+ nil)
+ (error t))
+ "`gc-cons-threshold' increased?" (> gc-cons-threshold 800000)
+ "Using gccemacs with emacs lisp native compilation (https://akrl.sdf.org/gccemacs.html)"
+ (or (and (fboundp 'native-comp-available-p)
+ (native-comp-available-p))
+ :optional)))
+
+(declare-function package-version-join "ext:package")
+(declare-function package-desc-version "ext:package")
+(declare-function package--alist "ext:package")
+
+(defun lsp-version ()
+ "Return string describing current version of `lsp-mode'."
+ (interactive)
+ (unless (featurep 'package)
+ (require 'package))
+ (let ((ver (format "lsp-mode %s, Emacs %s, %s"
+ (package-version-join
+ (package-desc-version
+ (car (alist-get 'lsp-mode (package--alist)))))
+ emacs-version
+ system-type)))
+ (if (called-interactively-p 'interactive)
+ (lsp--info "%s" ver)
+ ver)))
+
+
+
+;; org-mode/virtual-buffer
+
+(declare-function org-babel-get-src-block-info "ext:ob-core")
+(declare-function org-do-remove-indentation "ext:org-macs")
+(declare-function org-src-get-lang-mode "ext:org-src")
+(declare-function org-element-context "ext:org-element")
+
+(defun lsp--virtual-buffer-update-position ()
+ (-if-let (virtual-buffer (-first (-lambda ((&plist :in-range))
+ (funcall in-range))
+ lsp--virtual-buffer-connections))
+ (unless (equal virtual-buffer lsp--virtual-buffer)
+ (lsp-org))
+ (when lsp-managed-mode
+ (lsp-managed-mode -1)
+ (lsp-mode -1)
+ (setq lsp--buffer-workspaces nil)
+ (setq lsp--virtual-buffer nil)
+ (setq lsp-buffer-uri nil)
+
+ ;; force refresh of diagnostics
+ (run-hooks 'lsp-after-diagnostics-hook))))
+
+(defun lsp-virtual-buffer-on-change (start end length)
+ "Adjust on change event to be executed against the proper language server."
+ (let ((max-point (max end
+ (or (plist-get lsp--before-change-vals :end) 0)
+ (+ start length))))
+ (when-let ((virtual-buffer (-first (lambda (vb)
+ (let ((lsp--virtual-buffer vb))
+ (and (lsp-virtual-buffer-call :in-range start)
+ (lsp-virtual-buffer-call :in-range max-point))))
+ lsp--virtual-buffer-connections)))
+ (lsp-with-current-buffer virtual-buffer
+ (lsp-on-change start end length
+ (lambda (&rest _)
+ (list :range (lsp--range (list :character 0 :line 0)
+ lsp--virtual-buffer-point-max)
+ :text (lsp--buffer-content))))))))
+
+(defun lsp-virtual-buffer-before-change (start _end)
+ (when-let ((virtual-buffer (-first (lambda (vb)
+ (lsp-with-current-buffer vb
+ (lsp-virtual-buffer-call :in-range start)))
+ lsp--virtual-buffer-connections)))
+ (lsp-with-current-buffer virtual-buffer
+ (setq lsp--virtual-buffer-point-max
+ (lsp--point-to-position (lsp-virtual-buffer-call :last-point))))))
+
+(defun lsp-patch-on-change-event ()
+ (remove-hook 'after-change-functions #'lsp-on-change t)
+ (add-hook 'after-change-functions #'lsp-virtual-buffer-on-change nil t)
+ (add-hook 'before-change-functions #'lsp-virtual-buffer-before-change nil t))
+
+(defun lsp-kill-virtual-buffers ()
+ (mapc #'lsp-virtual-buffer-disconnect lsp--virtual-buffer-connections))
+
+(defun lsp--move-point-in-indentation (point indentation)
+ (save-excursion
+ (goto-char point)
+ (if (<= point (+ (point-at-bol) indentation))
+ (point-at-bol)
+ point)))
+
+(declare-function flycheck-checker-supports-major-mode-p "ext:flycheck")
+(declare-function flycheck-add-mode "ext:flycheck")
+(declare-function lsp-diagnostics-lsp-checker-if-needed "lsp-diagnostics")
+
+(defalias 'lsp-client-download-server-fn 'lsp--client-download-server-fn)
+
+(defun lsp-flycheck-add-mode (mode)
+ "Register flycheck support for MODE."
+ (lsp-diagnostics-lsp-checker-if-needed)
+ (unless (flycheck-checker-supports-major-mode-p 'lsp mode)
+ (flycheck-add-mode 'lsp mode)))
+
+(defun lsp-org ()
+ (interactive)
+ (-if-let ((virtual-buffer &as &plist :workspaces) (-first (-lambda ((&plist :in-range))
+ (funcall in-range))
+ lsp--virtual-buffer-connections))
+ (unless (equal lsp--virtual-buffer virtual-buffer)
+ (setq lsp--buffer-workspaces workspaces)
+ (setq lsp--virtual-buffer virtual-buffer)
+ (setq lsp-buffer-uri nil)
+ (lsp-mode 1)
+ (lsp-managed-mode 1)
+ (lsp-patch-on-change-event))
+
+ (save-excursion
+ (-let* (virtual-buffer
+ (wcb (lambda (f)
+ (with-current-buffer (plist-get virtual-buffer :buffer)
+ (-let* (((&plist :major-mode :buffer-file-name
+ :goto-buffer :workspaces) virtual-buffer)
+ (lsp--virtual-buffer virtual-buffer)
+ (lsp--buffer-workspaces workspaces))
+ (save-excursion
+ (funcall goto-buffer)
+ (funcall f))))))
+ ((&plist :begin :end :post-blank :language) (cl-second (org-element-context)))
+ ((&alist :tangle file-name) (cl-third (org-babel-get-src-block-info 'light)))
+
+ (file-name (if file-name
+ (f-expand file-name)
+ (user-error "You should specify file name in the src block header.")))
+ (begin-marker (progn
+ (goto-char begin)
+ (forward-line)
+ (set-marker (make-marker) (point))))
+ (end-marker (progn
+ (goto-char end)
+ (forward-line (1- (- post-blank)))
+ (set-marker (make-marker) (1+ (point)))))
+ (buf (current-buffer))
+ (src-block (buffer-substring-no-properties begin-marker
+ (1- end-marker)))
+ (indentation (with-temp-buffer
+ (insert src-block)
+
+ (goto-char (point-min))
+ (let ((indentation (current-indentation)))
+ (plist-put lsp--virtual-buffer :indentation indentation)
+ (org-do-remove-indentation)
+ (goto-char (point-min))
+ (- indentation (current-indentation))))))
+ (add-hook 'post-command-hook #'lsp--virtual-buffer-update-position nil t)
+
+ (when (fboundp 'flycheck-add-mode)
+ (lsp-flycheck-add-mode 'org-mode))
+
+ (setq lsp--virtual-buffer
+ (list
+ :in-range (lambda (&optional point)
+ (<= begin-marker (or point (point)) (1- end-marker)))
+ :goto-buffer (lambda () (goto-char begin-marker))
+ :buffer-string
+ (lambda ()
+ (let ((src-block (buffer-substring-no-properties
+ begin-marker
+ (1- end-marker))))
+ (with-temp-buffer
+ (insert src-block)
+
+ (goto-char (point-min))
+ (while (not (eobp))
+ (delete-region (point) (if (> (+ (point) indentation) (point-at-eol))
+ (point-at-eol)
+ (+ (point) indentation)))
+ (forward-line))
+ (buffer-substring-no-properties (point-min)
+ (point-max)))))
+ :buffer buf
+ :begin begin-marker
+ :end end-marker
+ :indentation indentation
+ :last-point (lambda () (1- end-marker))
+ :cur-position (lambda ()
+ (lsp-save-restriction-and-excursion
+ (list :line (- (lsp--cur-line)
+ (lsp--cur-line begin-marker))
+ :character (let ((character (- (point)
+ (line-beginning-position)
+ indentation)))
+ (if (< character 0)
+ 0
+ character)))))
+ :line/character->point (-lambda (line character)
+ (-let [inhibit-field-text-motion t]
+ (+ indentation
+ (lsp-save-restriction-and-excursion
+ (goto-char begin-marker)
+ (forward-line line)
+ (-let [line-end (line-end-position)]
+ (if (> character (- line-end (point)))
+ line-end
+ (forward-char character)
+ (point)))))))
+ :major-mode (org-src-get-lang-mode language)
+ :buffer-file-name file-name
+ :buffer-uri (lsp--path-to-uri file-name)
+ :with-current-buffer wcb
+ :buffer-live? (lambda (_) (buffer-live-p buf))
+ :buffer-name (lambda (_)
+ (propertize (format "%s(%s:%s)%s"
+ (buffer-name buf)
+ begin-marker
+ end-marker
+ language)
+ 'face 'italic))
+ :real->virtual-line (lambda (line)
+ (+ line (line-number-at-pos begin-marker) -1))
+ :real->virtual-char (lambda (char) (+ char indentation))
+ :cleanup (lambda ()
+ (set-marker begin-marker nil)
+ (set-marker end-marker nil))))
+ (setf virtual-buffer lsp--virtual-buffer)
+ (puthash file-name virtual-buffer lsp--virtual-buffer-mappings)
+ (push virtual-buffer lsp--virtual-buffer-connections)
+
+ ;; TODO: tangle only connected sections
+ (add-hook 'after-save-hook 'org-babel-tangle nil t)
+ (add-hook 'lsp-after-open-hook #'lsp-patch-on-change-event nil t)
+ (add-hook 'kill-buffer-hook #'lsp-kill-virtual-buffers nil t)
+
+ (setq lsp--buffer-workspaces
+ (lsp-with-current-buffer virtual-buffer
+ (lsp)
+ (plist-put virtual-buffer :workspaces (lsp-workspaces))
+ (lsp-workspaces)))))))
+
+(defun lsp-virtual-buffer-disconnect (virtual-buffer)
+ (interactive (list (or
+ lsp--virtual-buffer
+ (when lsp--virtual-buffer-connections
+ (lsp--completing-read "Select virtual buffer to disconnect: "
+ lsp--virtual-buffer-connections
+ (-lambda ((&plist :buffer-file-name))
+ buffer-file-name))))))
+ (-if-let ((&plist :buffer-file-name file-name :cleanup) virtual-buffer)
+ (progn
+ (lsp-with-current-buffer virtual-buffer
+ (lsp--text-document-did-close))
+ (setq lsp--virtual-buffer-connections (-remove-item virtual-buffer lsp--virtual-buffer-connections))
+ (when (eq virtual-buffer lsp--virtual-buffer)
+ (setf lsp--virtual-buffer nil))
+ (when cleanup (funcall cleanup))
+ (remhash file-name lsp--virtual-buffer-mappings)
+
+ (lsp--virtual-buffer-update-position)
+ (lsp--info "Disconnected from buffer %s" file-name))
+ (lsp--error "Nothing to disconnect from?")))
+
+
+
+(provide 'lsp-mode)
+;;; lsp-mode.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-modeline.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-modeline.el
new file mode 100644
index 0000000..09ea7d4
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-modeline.el
@@ -0,0 +1,354 @@
+;;; lsp-modeline.el --- LSP modeline features -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; LSP modeline
+;;
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-modeline nil
+ "LSP support for modeline"
+ :prefix "lsp-modeline-"
+ :group 'lsp-mode
+ :tag "LSP Modeline")
+
+(defcustom lsp-modeline-code-actions-kind-regex "$\\|quickfix.*\\|refactor.*"
+ "Regex for the code actions kinds to show in the modeline."
+ :type 'string
+ :group 'lsp-modeline)
+
+(defcustom lsp-modeline-code-actions-segments '(count icon)
+ "Define what should display on the modeline when code actions are available."
+ :type '(repeat (choice
+ (const :tag "Show the lightbulb icon" icon)
+ (const :tag "Show the name of the preferred code action" name)
+ (const :tag "Show the count of how many code actions available" count)))
+ :group 'lsp-modeline
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-modeline-code-action-fallback-icon "💡"
+ "Define what should display on the modeline when code actions are available."
+ :type 'string
+ :group 'lsp-modeline
+ :package-version '(lsp-mode . "7.1"))
+
+(defface lsp-modeline-code-actions-face
+ '((t :inherit homoglyph))
+ "Face used to code action text on modeline."
+ :group 'lsp-modeline)
+
+(defface lsp-modeline-code-actions-preferred-face
+ '((t :foreground "yellow"))
+ "Face used to code action text on modeline."
+ :group 'lsp-modeline)
+
+;;;###autoload
+(define-obsolete-variable-alias 'lsp-diagnostics-modeline-scope
+ 'lsp-modeline-diagnostics-scope "lsp-mode 7.0.1")
+
+(defcustom lsp-modeline-diagnostics-scope :workspace
+ "The modeline diagnostics scope."
+ :group 'lsp-modeline
+ :type '(choice (const :tag "File" :file)
+ (const :tag "Project" :workspace)
+ (const :tag "All Projects" :global))
+ :package-version '(lsp-mode . "6.3"))
+
+(declare-function all-the-icons-octicon "ext:all-the-icons" t t)
+(declare-function lsp-treemacs-errors-list "ext:lsp-treemacs" t)
+
+
+;; code actions
+
+(defvar-local lsp-modeline--code-actions-string nil
+ "Holds the current code action string on modeline.")
+
+(defun lsp-modeline--code-action-face (preferred-code-action)
+ "Return the face checking if there is any PREFERRED-CODE-ACTION."
+ (if preferred-code-action
+ 'lsp-modeline-code-actions-preferred-face
+ 'lsp-modeline-code-actions-face))
+
+(defun lsp-modeline--code-actions-icon (face)
+ "Build the icon for modeline code actions using FACE."
+ (if (require 'all-the-icons nil t)
+ (all-the-icons-octicon "light-bulb"
+ :face face
+ :v-adjust -0.0575)
+ (propertize lsp-modeline-code-action-fallback-icon 'face face)))
+
+(defun lsp-modeline--code-action-name (actions preferred-code-action-title)
+ "Return the code action name from ACTIONS and PREFERRED-CODE-ACTION-TITLE."
+ (or preferred-code-action-title
+ (->> actions
+ lsp-seq-first
+ lsp-modeline--code-action->string)))
+
+(defun lsp-modeline--code-action->string (action)
+ "Convert code ACTION to friendly string."
+ (->> action
+ lsp:code-action-title
+ (replace-regexp-in-string "[\n\t ]+" " ")))
+
+(defun lsp-modeline--build-code-actions-segments (actions)
+ "Build the code ACTIONS string from the defined segments."
+ (let* ((preferred-code-action (-some->> actions
+ (-first #'lsp:code-action-is-preferred?)
+ lsp-modeline--code-action->string))
+ (face (lsp-modeline--code-action-face preferred-code-action)))
+ (mapconcat
+ (lambda (segment)
+ (pcase segment
+ ('icon (lsp-modeline--code-actions-icon face))
+ ('name (propertize (lsp-modeline--code-action-name actions preferred-code-action)
+ 'face face))
+ ('count (propertize (number-to-string (seq-length actions))
+ 'face face))))
+ lsp-modeline-code-actions-segments " ")))
+
+(defun lsp-modeline--build-code-actions-string (actions)
+ "Build the string to be presented on modeline for code ACTIONS."
+ (-let* ((single-action? (= (length actions) 1))
+ (keybinding (concat "("
+ (-some->> #'lsp-execute-code-action
+ where-is-internal
+ (-find (lambda (o)
+ (not (member (aref o 0) '(menu-bar normal-state)))))
+ key-description)
+ ")"))
+ (built-string (lsp-modeline--build-code-actions-segments actions))
+ (preferred-code-action (-some->> actions
+ (-first #'lsp:code-action-is-preferred?)
+ lsp-modeline--code-action->string)))
+ (add-text-properties 0 (length built-string)
+ (list 'help-echo
+ (concat (format "Apply code actions %s\nmouse-1: " keybinding)
+ (if single-action?
+ (lsp-modeline--code-action-name actions preferred-code-action)
+ "select from multiple code actions"))
+ 'mouse-face 'mode-line-highlight
+ 'local-map (make-mode-line-mouse-map
+ 'mouse-1 (lambda ()
+ (interactive)
+ (if single-action?
+ (lsp-execute-code-action (lsp-seq-first actions))
+ (lsp-execute-code-action (lsp--select-action actions))))))
+ built-string)
+ (unless (string= "" built-string)
+ (concat built-string " "))))
+
+(defun lsp--modeline-update-code-actions (actions)
+ "Update modeline with new code ACTIONS."
+ (when lsp-modeline-code-actions-kind-regex
+ (setq actions (seq-filter (-lambda ((&CodeAction :kind?))
+ (or (not kind?)
+ (s-match lsp-modeline-code-actions-kind-regex kind?)))
+ actions)))
+ (setq lsp-modeline--code-actions-string
+ (if (seq-empty-p actions) ""
+ (lsp-modeline--build-code-actions-string actions)))
+ (force-mode-line-update))
+
+(defun lsp-modeline--check-code-actions (&rest _)
+ "Request code actions to update modeline for given BUFFER."
+ (when (lsp-feature? "textDocument/codeAction")
+ (lsp-request-async
+ "textDocument/codeAction"
+ (lsp--text-document-code-action-params)
+ #'lsp--modeline-update-code-actions
+ :mode 'unchanged
+ :cancel-token :lsp-modeline-code-actions)))
+
+(defun lsp-modeline--enable-code-actions ()
+ "Enable code actions on modeline mode."
+ (when (and lsp-modeline-code-actions-enable
+ (lsp-feature? "textDocument/codeAction"))
+ (lsp-modeline-code-actions-mode 1)))
+
+(defun lsp-modeline--disable-code-actions ()
+ "Disable code actions on modeline mode."
+ (lsp-modeline-code-actions-mode -1))
+
+;;;###autoload
+(define-minor-mode lsp-modeline-code-actions-mode
+ "Toggle code actions on modeline."
+ :group 'lsp-modeline
+ :global nil
+ :lighter ""
+ (cond
+ (lsp-modeline-code-actions-mode
+ (add-to-list 'global-mode-string '(t (:eval lsp-modeline--code-actions-string)))
+
+ (add-hook 'lsp-on-idle-hook 'lsp-modeline--check-code-actions nil t)
+ (add-hook 'lsp-configure-hook #'lsp-modeline--enable-code-actions nil t)
+ (add-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-code-actions nil t))
+ (t
+ (remove-hook 'lsp-on-idle-hook 'lsp-modeline--check-code-actions t)
+ (remove-hook 'lsp-configure-hook #'lsp-modeline--enable-code-actions t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-code-actions t)
+ (setq global-mode-string (remove '(t (:eval lsp-modeline--code-actions-string)) global-mode-string)))))
+
+
+;; diagnostics
+
+(defvar-local lsp-modeline--diagnostics-string nil
+ "Value of current buffer diagnostics statistics.")
+
+(defvar lsp-modeline--diagnostics-wks->strings nil
+ "Plist of workspaces to their modeline strings.
+The `:global' workspace is global one.")
+
+(defun lsp-modeline-diagnostics-statistics ()
+ "Calculate diagnostics statistics based on `lsp-modeline-diagnostics-scope'."
+ (let ((diagnostics (cond
+ ((equal :file lsp-modeline-diagnostics-scope)
+ (list (lsp--get-buffer-diagnostics)))
+ (t (->> (eq :workspace lsp-modeline-diagnostics-scope)
+ (lsp-diagnostics)
+ (ht-values)))))
+ (stats (make-vector lsp/diagnostic-severity-max 0))
+ strs
+ (i 0))
+ (mapc (lambda (buf-diags)
+ (mapc (lambda (diag)
+ (-let [(&Diagnostic? :severity?) diag]
+ (when severity?
+ (cl-incf (aref stats severity?)))))
+ buf-diags))
+ diagnostics)
+ (while (< i lsp/diagnostic-severity-max)
+ (when (> (aref stats i) 0)
+ (setq strs
+ (nconc strs
+ `(,(propertize
+ (format "%s" (aref stats i))
+ 'face
+ (cond
+ ((= i lsp/diagnostic-severity-error) 'error)
+ ((= i lsp/diagnostic-severity-warning) 'warning)
+ ((= i lsp/diagnostic-severity-information) 'success)
+ ((= i lsp/diagnostic-severity-hint) 'success)))))))
+ (cl-incf i))
+ (-> (s-join "/" strs)
+ (propertize 'mouse-face 'mode-line-highlight
+ 'help-echo "mouse-1: Show diagnostics"
+ 'local-map (when (require 'lsp-treemacs nil t)
+ (make-mode-line-mouse-map
+ 'mouse-1 #'lsp-treemacs-errors-list))))))
+
+(defun lsp-modeline--diagnostics-reset-modeline-cache ()
+ "Reset the modeline diagnostics cache."
+ (plist-put lsp-modeline--diagnostics-wks->strings (car (lsp-workspaces)) nil)
+ (plist-put lsp-modeline--diagnostics-wks->strings :global nil)
+ (setq lsp-modeline--diagnostics-string nil))
+
+(defun lsp-modeline--diagnostics-update-modeline ()
+ "Update diagnostics modeline string."
+ (cl-labels ((calc-modeline ()
+ (let ((str (lsp-modeline-diagnostics-statistics)))
+ (if (string-empty-p str) ""
+ (concat str " ")))))
+ (setq lsp-modeline--diagnostics-string
+ (cl-case lsp-modeline-diagnostics-scope
+ (:file (or lsp-modeline--diagnostics-string
+ (calc-modeline)))
+ (:workspace
+ (let ((wk (car (lsp-workspaces))))
+ (or (plist-get lsp-modeline--diagnostics-wks->strings wk)
+ (let ((ml (calc-modeline)))
+ (setq lsp-modeline--diagnostics-wks->strings
+ (plist-put lsp-modeline--diagnostics-wks->strings wk ml))
+ ml))))
+ (:global
+ (or (plist-get lsp-modeline--diagnostics-wks->strings :global)
+ (let ((ml (calc-modeline)))
+ (setq lsp-modeline--diagnostics-wks->strings
+ (plist-put lsp-modeline--diagnostics-wks->strings :global ml))
+ ml)))))))
+
+(defun lsp-modeline--enable-diagnostics ()
+ "Enable diagnostics on modeline mode."
+ (when (and lsp-modeline-diagnostics-enable
+ (lsp-feature? "textDocument/publishDiagnostics"))
+ (lsp-modeline-diagnostics-mode 1)))
+
+(defun lsp-modeline--disable-diagnostics ()
+ "Disable diagnostics on modeline mode."
+ (lsp-modeline-diagnostics-mode -1))
+
+;;;###autoload
+(define-obsolete-function-alias 'lsp-diagnostics-modeline-mode
+ 'lsp-modeline-diagnostics-mode "lsp-mode 7.0.1")
+
+;;;###autoload
+(define-minor-mode lsp-modeline-diagnostics-mode
+ "Toggle diagnostics modeline."
+ :group 'lsp-modeline
+ :global nil
+ :lighter ""
+ (cond
+ (lsp-modeline-diagnostics-mode
+ (add-hook 'lsp-configure-hook #'lsp-modeline--enable-diagnostics nil t)
+ (add-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-diagnostics nil t)
+ (add-to-list 'global-mode-string '(t (:eval (lsp-modeline--diagnostics-update-modeline))))
+ (add-hook 'lsp-diagnostics-updated-hook 'lsp-modeline--diagnostics-reset-modeline-cache))
+ (t
+ (remove-hook 'lsp-configure-hook #'lsp-modeline--enable-diagnostics t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-diagnostics t)
+ (remove-hook 'lsp-diagnostics-updated-hook 'lsp-modeline--diagnostics-reset-modeline-cache)
+ (setq global-mode-string (remove '(t (:eval (lsp-modeline--diagnostics-update-modeline))) global-mode-string)))))
+
+
+;; workspace status
+
+(defun lsp-modeline--workspace-status-string ()
+ "Build the workspace status string."
+ '(t (:eval (-keep #'lsp--workspace-status-string (lsp-workspaces)))))
+
+(defun lsp-modeline--enable-workspace-status ()
+ "Enable workspace status on modeline."
+ (let ((status (lsp-modeline--workspace-status-string)))
+ (setq-local global-mode-string (if (-contains? global-mode-string status)
+ global-mode-string
+ (cons status global-mode-string)))))
+
+(defun lsp-modeline--disable-workspace-status ()
+ "Disable workspace status on modeline."
+ (let ((status (lsp-modeline--workspace-status-string)))
+ (setq-local global-mode-string (remove status global-mode-string))))
+
+;;;###autoload
+(define-minor-mode lsp-modeline-workspace-status-mode
+ "Toggle workspace status on modeline."
+ :group 'lsp-modeline
+ :global nil
+ :lighter ""
+ (cond
+ (lsp-modeline-workspace-status-mode
+ (add-hook 'lsp-configure-hook #'lsp-modeline--enable-workspace-status nil t)
+ (add-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-workspace-status nil t))
+ (t
+ (remove-hook 'lsp-configure-hook #'lsp-modeline--enable-workspace-status t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-modeline--disable-workspace-status t))))
+
+(lsp-consistency-check lsp-modeline)
+
+(provide 'lsp-modeline)
+;;; lsp-modeline.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nim.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nim.el
new file mode 100644
index 0000000..5418137
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nim.el
@@ -0,0 +1,45 @@
+;;; lsp-nim.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, nim
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Nim Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+;; Nim
+(defgroup lsp-nimlsp nil
+ "LSP support for Nim, using nimlsp."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/PMunch/nimlsp"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection "nimlsp")
+ :major-modes '(nim-mode)
+ :priority -1
+ :server-id 'nimls))
+
+
+(lsp-consistency-check lsp-nim)
+
+(provide 'lsp-nim)
+;;; lsp-nim.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nix.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nix.el
new file mode 100644
index 0000000..2e1c0b5
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-nix.el
@@ -0,0 +1,48 @@
+;;; lsp-nix.el --- lsp-mode nix integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 lsp-mode maintainers
+
+;; Author: Seong Yong-ju <sei40kr@gmail.com>
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Client for the rnix language server.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-nix nil
+ "LSP support for Nix, using rnix-lsp."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/nix-community/rnix-lsp"))
+
+(defcustom lsp-nix-server-path "rnix-lsp"
+ "Executable path for the server."
+ :group 'lsp-nix
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-nix-server-path))
+ :major-modes '(nix-mode)
+ :server-id 'rnix-lsp))
+
+(lsp-consistency-check lsp-nix)
+
+(provide 'lsp-nix)
+;;; lsp-nix.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ocaml.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ocaml.el
new file mode 100644
index 0000000..b1e1003
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-ocaml.el
@@ -0,0 +1,84 @@
+;;; lsp-ocaml.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, ocaml
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Ocaml Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-ocaml nil
+ "LSP support for OCaml, using ocaml-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/freebroccolo/ocaml-language-server"))
+
+(define-obsolete-variable-alias
+ 'lsp-ocaml-ocaml-lang-server-command
+ 'lsp-ocaml-lang-server-command
+ "lsp-mode 6.1")
+
+(defcustom lsp-ocaml-lang-server-command
+ '("ocaml-language-server" "--stdio")
+ "Command to start ocaml-language-server."
+ :group 'lsp-ocaml
+ :type '(choice
+ (string :tag "Single string value")
+ (repeat :tag "List of string values"
+ string)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda () lsp-ocaml-lang-server-command))
+ :major-modes '(reason-mode caml-mode tuareg-mode)
+ :priority -1
+ :server-id 'ocaml-ls))
+
+(defgroup lsp-ocaml-lsp-server nil
+ "LSP support for OCaml, using ocaml-lsp-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/ocaml/ocaml-lsp"))
+
+(define-obsolete-variable-alias 'lsp-merlin 'lsp-ocaml-lsp-server "lsp-mode 6.1")
+(define-obsolete-variable-alias 'lsp-merlin-command 'lsp-ocaml-lsp-server-command "lsp-mode 6.1")
+
+(defcustom lsp-ocaml-lsp-server-command
+ '("ocamllsp")
+ "Command to start ocaml-language-server."
+ :group 'lsp-ocaml
+ :type '(choice
+ (string :tag "Single string value")
+ (repeat :tag "List of string values"
+ string)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection
+ (lsp-stdio-connection (lambda () lsp-ocaml-lsp-server-command))
+ :major-modes '(reason-mode caml-mode tuareg-mode)
+ :priority 0
+ :server-id 'ocaml-lsp-server))
+
+
+(lsp-consistency-check lsp-ocaml)
+
+(provide 'lsp-ocaml)
+;;; lsp-ocaml.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-perl.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-perl.el
new file mode 100644
index 0000000..07ef6d0
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-perl.el
@@ -0,0 +1,117 @@
+;;; lsp-perl.el --- lsp-perl config -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 lsp-mode developers
+
+;; Author: Hiroki Noda <kubo39@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-perl client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-perl nil
+ "LSP support for Perl"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/richterger/Perl-LanguageServer")
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-perl-language-server-path "perl"
+ "Path to perl interpreter."
+ :type 'string
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-perl-language-server-port 13603
+ "Choose listen port."
+ :type 'integer
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-perl-language-server-client-version "2.1.0"
+ "Choose client version."
+ :type 'string
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-perl-perl-cmd nil
+ "Path to perl interpreter used in Perl Language Server.
+Defaults to `perl' if nil."
+ :type 'string
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.0.1"))
+(defcustom lsp-perl-perl-inc nil
+ "A vector of paths to add to perl library path."
+ :type 'lsp-string-vector
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.0.1"))
+(defcustom lsp-perl-file-filter nil
+ "A vector of directories filtering perl file.
+Defaults to `[\".pm\" \".pl\"]' if nil."
+ :type 'lsp-string-vector
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.0.1"))
+(defcustom lsp-perl-ignore-dirs nil
+ "A vector of directories to ignore.
+Defaults to `[\".vscode\" \".git\" \".svn\"]' if nil."
+ :type 'lsp-string-vector
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defcustom lsp-perl-show-local-vars nil
+ "If true, show also local variables in symbol view.
+Defaults to false if nil"
+ :type 'boolean
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-perl-log-level nil
+ "Log level 0-2.
+Defaults to 0."
+ :type 'integer
+ :group 'lsp-perl
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-register-custom-settings
+ '(("perl.perlCmd" lsp-perl-perl-cmd)
+ ("perl.perlInc" lsp-perl-perl-inc)
+ ("perl.fileFilter" lsp-perl-file-filter)
+ ("perl.ignoreDirs" lsp-perl-ignore-dirs)
+ ("perl.showLocalVars" lsp-perl-show-local-vars t)
+ ("perl.logLevel" lsp-perl-log-level)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ (list lsp-perl-language-server-path
+ "-MPerl::LanguageServer" "-e" "Perl::LanguageServer::run" "--"
+ (format "--port %d --version %s"
+ lsp-perl-language-server-port lsp-perl-language-server-client-version))))
+ :major-modes '(perl-mode cperl-mode)
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "perl"))))
+ :priority -1
+ :server-id 'perl-language-server))
+
+(lsp-consistency-check lsp-perl)
+
+(provide 'lsp-perl)
+;;; lsp-perl.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-php.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-php.el
new file mode 100644
index 0000000..975a527
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-php.el
@@ -0,0 +1,433 @@
+;;; lsp-php.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, php
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the PHP Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'lsp-protocol)
+
+;; PHP Language Server
+(defgroup lsp-php nil
+ "LSP support for PHP, using php-language-server."
+ :link '(url-link "https://github.com/felixfbecker/php-language-server")
+ :group 'lsp-mode)
+
+(defun lsp-php-get-composer-dir ()
+ "Get composer home directory if possible."
+ (if (executable-find "composer")
+ (replace-regexp-in-string "\n$" "" (shell-command-to-string "composer config --global home"))
+ "~/.composer"))
+
+(defcustom lsp-php-composer-dir nil
+ "Home directory of composer."
+ :group 'lsp-php
+ :type 'string)
+
+(defcustom lsp-clients-php-server-command nil
+ "Install directory for php-language-server."
+ :group 'lsp-php
+ :type '(repeat string))
+
+(defun lsp-php--create-connection ()
+ "Create lsp connection."
+ (lsp-stdio-connection
+ (lambda ()
+ (unless lsp-php-composer-dir
+ (setq lsp-php-composer-dir (lsp-php-get-composer-dir)))
+ (unless lsp-clients-php-server-command
+ (setq lsp-clients-php-server-command
+ `("php",
+ (expand-file-name
+ (f-join lsp-php-composer-dir "vendor/felixfbecker/language-server/bin/php-language-server.php")))))
+ lsp-clients-php-server-command)
+ (lambda ()
+ (if (and (cdr lsp-clients-php-server-command)
+ (eq (string-match-p "php[0-9.]*\\'" (car lsp-clients-php-server-command)) 0))
+ ;; Start with the php command and the list has more elems. Test the existence of the PHP script.
+ (let ((php-file (nth 1 lsp-clients-php-server-command)))
+ (or (file-exists-p php-file)
+ (progn
+ (lsp-log "%s is not present." php-file)
+ nil)))
+ t))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-php--create-connection)
+ :activation-fn (lsp-activate-on "php")
+ :priority -3
+ :server-id 'php-ls))
+
+;;; Intelephense
+(defgroup lsp-intelephense nil
+ "LSP support for PHP, using Intelephense."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/bmewburn/vscode-intelephense")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-files-max-size 1000000
+ "Maximum file size in bytes."
+ :type 'number
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-files-associations
+ ["*.php" "*.phtml"]
+ "Configure glob patterns to make files available for language
+server features."
+ :type '(repeat string)
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-files-exclude
+ ["**/.git/**" "**/.svn/**" "**/.hg/**" "**/CVS/**" "**/.DS_Store/**"
+ "**/node_modules/**" "**/bower_components/**" "**/vendor/**/{Test,test,Tests,tests}/**"]
+ "Configure glob patterns to exclude certain files and folders
+from all language server features."
+ :type '(repeat string)
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-stubs
+ ["apache" "bcmath" "bz2" "calendar"
+ "com_dotnet" "Core" "ctype" "curl" "date" "dba" "dom" "enchant"
+ "exif" "fileinfo" "filter" "fpm" "ftp" "gd" "hash" "iconv" "imap" "interbase"
+ "intl" "json" "ldap" "libxml" "mbstring" "mcrypt" "meta" "mssql" "mysqli"
+ "oci8" "odbc" "openssl" "pcntl" "pcre" "PDO" "pdo_ibm" "pdo_mysql"
+ "pdo_pgsql" "pdo_sqlite" "pgsql" "Phar" "posix" "pspell" "readline" "recode"
+ "Reflection" "regex" "session" "shmop" "SimpleXML" "snmp" "soap" "sockets"
+ "sodium" "SPL" "sqlite3" "standard" "superglobals" "sybase" "sysvmsg"
+ "sysvsem" "sysvshm" "tidy" "tokenizer" "wddx" "xml" "xmlreader" "xmlrpc"
+ "xmlwriter" "Zend OPcache" "zip" "zlib"]
+ "Configure stub files for built in symbols and common
+extensions. The default setting includes PHP core and all
+bundled extensions."
+ :type '(repeat string)
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-completion-insert-use-declaration t
+ "Use declarations will be automatically inserted for namespaced
+classes, traits, interfaces, functions, and constants."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-completion-fully-qualify-global-constants-and-functions nil
+ "Global namespace constants and functions will be fully
+qualified (prefixed with a backslash)."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-completion-trigger-parameter-hints t
+ "Method and function completions will include parentheses and
+trigger parameter hints."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-completion-max-items 100
+ "The maximum number of completion items returned per request."
+ :type 'number
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-format-enable t
+ "Enables formatting."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-licence-key nil
+ "Enter your intelephense licence key here to access premium
+features."
+ :type 'string
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-telemetry-enabled nil
+ "Anonymous usage and crash data will be sent to Azure
+Application Insights."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-rename-exclude
+ ["**/vendor/**"]
+ "Glob patterns to exclude files and folders from having symbols
+renamed. Rename operation will fail if references and/or
+definitions are found in excluded files/folders."
+ :type '(repeat string)
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-trace-server "off"
+ "Traces the communication between VSCode and the intelephense
+language server."
+ :type '(choice (:tag "off" "messages" "verbose"))
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-storage-path
+ (expand-file-name (locate-user-emacs-file "lsp-cache"))
+ "Optional absolute path to storage dir."
+ :type 'directory
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-intelephense-clear-cache nil
+ "Optional flag to clear server state."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-intelephense-multi-root t
+ "Flag to control if the server supports multi-root projects."
+ :type 'boolean
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.3"))
+
+(lsp-register-custom-settings
+ '(("intelephense.trace.server" lsp-intelephense-trace-server)
+ ("intelephense.rename.exclude" lsp-intelephense-rename-exclude)
+ ("intelephense.telemetry.enabled" lsp-intelephense-telemetry-enabled t)
+ ("intelephense.format.enable" lsp-intelephense-format-enable t)
+ ("intelephense.completion.maxItems" lsp-intelephense-completion-max-items)
+ ("intelephense.completion.triggerParameterHints" lsp-intelephense-completion-trigger-parameter-hints t)
+ ("intelephense.completion.fullyQualifyGlobalConstantsAndFunctions" lsp-intelephense-completion-fully-qualify-global-constants-and-functions t)
+ ("intelephense.completion.insertUseDeclaration" lsp-intelephense-completion-insert-use-declaration t)
+ ("intelephense.stubs" lsp-intelephense-stubs)
+ ("intelephense.files.exclude" lsp-intelephense-files-exclude)
+ ("intelephense.files.associations" lsp-intelephense-files-associations)
+ ("intelephense.files.maxSize" lsp-intelephense-files-max-size)))
+
+(define-obsolete-variable-alias
+ 'lsp-clients-php-iph-server-command
+ 'lsp-intelephense-server-command
+ "lsp-mode 6.1")
+
+(defcustom lsp-intelephense-server-command
+ `("intelephense" "--stdio")
+ "Command to start Intelephense."
+ :type '(repeat string)
+ :group 'lsp-intelephense
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-dependency 'intelephense
+ '(:system "intelephense")
+ '(:npm :package "intelephense"
+ :path "intelephense"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find
+ (cl-first lsp-intelephense-server-command))
+ (lsp-package-path 'intelephense))
+ ,@(cl-rest lsp-intelephense-server-command))))
+ :activation-fn (lsp-activate-on "php")
+ :priority -1
+ :notification-handlers (ht ("indexingStarted" #'ignore)
+ ("indexingEnded" #'ignore))
+ :initialization-options (lambda ()
+ (list :storagePath lsp-intelephense-storage-path
+ :licenceKey lsp-intelephense-licence-key
+ :clearCache lsp-intelephense-clear-cache))
+ :multi-root lsp-intelephense-multi-root
+ :completion-in-comments? t
+ :server-id 'iph
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'intelephense
+ callback error-callback))))
+
+
+;;; Serenata
+(defgroup lsp-serenata nil
+ "LSP support for the PHP programming language, using serenata."
+ :group 'lsp-mode
+ :link '(url-link "https://gitlab.com/Serenata/Serenata")
+ :package-version '(lsp-mode . "7.0"))
+
+(defcustom lsp-serenata-server-path
+ "serenata.phar"
+ "Path to the Serenata Language Server phar file.
+It can be downloaded from https://gitlab.com/Serenata/Serenata/-/releases."
+ :group 'lsp-serenata
+ :type 'file)
+
+(defcustom lsp-serenata-uris
+ []
+ "A list of folders to index for your project.
+This does not have to include the root of the project itself, in
+case you have need of an exotic configuration where the root of
+the project is at some location but your actual PHP code is
+somewhere else. Note that if you are running Serenata in a
+container, you will have to ensure that these URI's are mapped
+inside it. Avoid using file paths containing spaces. This is
+currently broken due to apparent PHP quirks. By default, the
+value is taken from the lsp workspace location."
+ :group 'lsp-serenata
+ :type 'lsp-string-vector)
+
+(defcustom lsp-serenata-php-version
+ 7.3
+ "Allows you to specify the PHP version your project is written in.
+At the moment this directive is still ignored, but it will
+influence functionality such as refactoring in the future, where
+older PHP versions may not support scalar type hints, which may
+then be omitted from places such as getters and setters."
+ :group 'lsp-serenata
+ :type 'number)
+
+(defcustom lsp-serenata-file-extensions
+ ["php"]
+ "List of file extensions (without dot) to process.
+Files that do not match this whitelist will be ignored during
+indexing. Usually you'll want to set this to at least include
+php, as it is the most common PHP extension. phpt is not
+included by default as it is often used to contain test code that
+is not directly part of the code. Note that for existing
+projects, removing extensions will not not automatically prune
+files having them from the index if they are already present.
+Adding new ones will cause the files having them to be picked up
+on the next project initialization."
+ :group 'lsp-serenata
+ :type 'lsp-string-vector)
+
+(defcustom lsp-serenata-index-database-uri (lsp--path-to-uri (f-join user-emacs-directory "index.sqlite"))
+ "The location to store the index database.
+Note that, as the index database uses SQLite and WAL mode,
+additional files (usually two) may be generated and used in the
+same folder. Note also that Serenata relies on the Doctrine DBAL
+library as well as the SQLite backends in PHP, which may not
+support non-file URI's, which may prevent you from using these."
+ :group 'lsp-serenata
+ :type 'file)
+
+(defcustom lsp-serenata-exclude-path-expressions ["/.+Test.php$/"]
+ "One or more expressions of paths to ignore.
+This uses Symfony's Finder in the background, so this means you
+can configure anything here that can also be passed to the name
+function, which includes plain strings, globs, as well as regular
+expressions. Note that for existing projects, modifying these
+will not not automatically prune them from the index if they are
+already present."
+ :group 'lsp-serenata
+ :type 'lsp-string-vector)
+
+(defun lsp-serenata-server-start-fun (port)
+ "Define serenata start function, it requires a PORT."
+ `(,lsp-serenata-server-path
+ "-u" ,(number-to-string port)))
+
+(defun lsp-serenata-init-options ()
+ "Init options for lsp-serenata."
+ `( :configuration ( :uris ,lsp-serenata-uris
+ :indexDatabaseUri ,lsp-serenata-index-database-uri
+ :phpVersion ,lsp-serenata-php-version
+ :excludedPathExpressions ,lsp-serenata-exclude-path-expressions
+ :fileExtensions ,lsp-serenata-file-extensions)))
+
+
+(lsp-interface (serenata:didProgressIndexing (:sequenceOfIndexedItem :totalItemsToIndex :progressPercentage :folderUri :fileUri :info) nil ))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-tcp-connection 'lsp-serenata-server-start-fun)
+ :activation-fn (lsp-activate-on "php")
+ :priority -2
+ :notification-handlers (ht ("serenata/didProgressIndexing"
+ (lambda (_server data)
+ (lsp-log "%s" (lsp:serenata-did-progress-indexing-info data)))))
+
+ :initialization-options #'lsp-serenata-init-options
+ :initialized-fn (lambda (workspace)
+ (when (equal (length lsp-serenata-uris) 0)
+ (let* ((lsp-root (lsp--path-to-uri (lsp-workspace-root))))
+ (setq lsp-serenata-uris (vector lsp-root))))
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "serenata"))))
+ :server-id 'serenata))
+
+;;; phpactor
+
+(defgroup lsp-phpactor nil
+ "LSP support for Phpactor."
+ :link '(url-link "https://github.com/phpactor/phpactor")
+ :group 'lsp-mode)
+
+(defcustom lsp-phpactor-path nil
+ "Path to the `phpactor' command."
+ :group 'lsp-phpactor
+ :type "string")
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ (lambda ()
+ (unless lsp-php-composer-dir
+ (setq lsp-php-composer-dir (lsp-php-get-composer-dir)))
+ (unless lsp-phpactor-path
+ (setq lsp-phpactor-path (f-join lsp-php-composer-dir "vendor/phpactor/phpactor/bin/phpactor")))
+ (list lsp-phpactor-path "language-server")))
+ :activation-fn (lsp-activate-on "php")
+ ;; `phpactor' is not really that feature-complete: it doesn't support
+ ;; `textDocument/showOccurence' and sometimes errors (e.g. find references on
+ ;; a global free-standing function).
+ :priority -4
+ ;; Even though `phpactor' itself supports no options, this needs to be
+ ;; serialized as an empty object (otherwise the LS won't even start, due to a
+ ;; type error).
+ :initialization-options (ht)
+ :server-id 'phpactor))
+
+(defcustom lsp-phpactor-extension-alist '(("Phpstan" . "phpactor/language-server-phpstan-extension")
+ ("Behat" . "phpactor/behat-extension")
+ ("PHPUnit" . "phpactor/phpunit-extension"))
+ "Alist mapping extension names to `composer' packages.
+These extensions can be installed using
+`lsp-phpactor-install-extension'."
+ :type '(alist :key-type "string" :value-type "string")
+ :group 'lsp-phpactor)
+
+(defun lsp-phpactor-install-extension (extension)
+ "Install a `phpactor' EXTENSION.
+See `lsp-phpactor-extension-alist' and
+https://phpactor.readthedocs.io/en/develop/extensions.html."
+ (interactive (list (completing-read "Select extension: "
+ lsp-phpactor-extension-alist)))
+ (compilation-start
+ (format "%s extension:install %s"
+ (shell-quote-argument (expand-file-name lsp-phpactor-path))
+ (shell-quote-argument
+ (cdr (assoc extension lsp-phpactor-extension-alist))))
+ nil
+ (lambda (_mode)
+ (format "*Phpactor install %s*" extension))))
+
+(lsp-consistency-check lsp-php)
+
+(provide 'lsp-php)
+;;; lsp-php.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-prolog.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-prolog.el
new file mode 100644
index 0000000..084f0ee
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-prolog.el
@@ -0,0 +1,55 @@
+;;; lsp-prolog.el --- Prolog Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 James Cash
+
+;; Author: James Cash <james.nvc@gmail.com>
+;; Keywords: languages,tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-prolog client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-prolog nil
+ "LSP support for Prolog."
+ :link '(url-link "https://github.com/jamesnvc/lsp_server")
+ :group 'lsp-mode
+ :tag "Lsp Prolog")
+
+(defcustom lsp-prolog-server-command '("swipl"
+ "-g" "use_module(library(lsp_server))."
+ "-g" "lsp_server:main"
+ "-t" "halt"
+ "--" "stdio")
+ "The prolog-lsp server command."
+ :group 'lsp-prolog
+ :risky t
+ :type 'list)
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () lsp-prolog-server-command))
+ :major-modes '(prolog-mode)
+ :multi-root t
+ :server-id 'prolog-lsp))
+
+(lsp-consistency-check lsp-prolog)
+
+(provide 'lsp-prolog)
+;;; lsp-prolog.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-protocol.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-protocol.el
new file mode 100644
index 0000000..50bcf3d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-protocol.el
@@ -0,0 +1,752 @@
+;;; lsp-protocol.el --- Language Sever Protocol Bindings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Autogenerated bindings from lsp4j using
+;; https://github.com/victools/jsonschema-generator+scrips to generate
+;; scripts/generated.protocol.schema.json and then
+;; scripts/lsp-generate-bindings.el
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'dash)
+(require 'ht)
+(require 's)
+
+(eval-and-compile
+ (defun lsp-keyword->symbol (keyword)
+ "Convert a KEYWORD to symbol."
+ (intern (substring (symbol-name keyword) 1)))
+
+ (defun lsp-keyword->string (keyword)
+ "Convert a KEYWORD to string."
+ (substring (symbol-name keyword) 1))
+
+ (defvar lsp-use-plists nil))
+
+(defmacro lsp-interface (&rest interfaces)
+ "Generate LSP bindings from INTERFACES triplet.
+
+Example usage with `dash`.
+
+\(-let [(&ApplyWorkspaceEditResponse
+ :failure-reason?) (ht (\"failureReason\" \"...\"))]
+ failure-reason?)
+
+\(fn (INTERFACE-NAME-1 REQUIRED-FIELDS-1 OPTIONAL-FIELDS-1) (INTERFACE-NAME-2 REQUIRED-FIELDS-2 OPTIONAL-FIELDS-2) ...)"
+ (with-case-table ascii-case-table
+ (->> interfaces
+ (-map (-lambda ((interface required optional))
+ (let ((params (nconc
+ (-map (lambda (param-name)
+ (cons
+ (intern (concat ":" (s-dashed-words (symbol-name param-name)) "?"))
+ param-name))
+ optional)
+ (-map (lambda (param-name)
+ (cons (intern (concat ":" (s-dashed-words (symbol-name param-name))))
+ param-name))
+ required))))
+ (cl-list*
+ `(defun ,(intern (format "dash-expand:&%s" interface)) (key source)
+ (unless (or (member key ',(-map #'cl-first params))
+ (s-starts-with? ":_" (symbol-name key)))
+ (error "Unknown key: %s. Available keys: %s" key ',(-map #'cl-first params)))
+ ,(if lsp-use-plists
+ ``(plist-get ,source
+ ,(if (s-starts-with? ":_" (symbol-name key))
+ key
+ (cl-rest (assoc key ',params))))
+ ``(gethash ,(if (s-starts-with? ":_" (symbol-name key))
+ (substring (symbol-name key) 1)
+ (substring (symbol-name
+ (cl-rest (assoc key ',params)))
+ 1))
+ ,source)))
+ `(defun ,(intern (format "dash-expand:&%s?" interface)) (key source)
+ (unless (member key ',(-map #'cl-first params))
+ (error "Unknown key: %s. Available keys: %s" key ',(-map #'cl-first params)))
+ ,(if lsp-use-plists
+ ``(plist-get ,source
+ ,(if (s-starts-with? ":_" (symbol-name key))
+ key
+ (cl-rest (assoc key ',params))))
+ ``(when (ht? ,source)
+ (gethash ,(substring (symbol-name
+ (cl-rest (assoc key ',params)))
+ 1)
+ ,source))))
+
+ `(defun ,(intern (format "lsp-%s?" (s-dashed-words (symbol-name interface)))) (object)
+ (cond
+ ((ht? object)
+ (-all? (let ((keys (ht-keys object)))
+ (lambda (prop)
+ (member prop keys)))
+ ',(-map (lambda (field-name)
+ (substring (symbol-name field-name) 1))
+ required)))
+ ((listp object) (-all? (lambda (prop)
+ (plist-member object prop))
+ ',required))))
+ `(cl-defun ,(intern (format "lsp-make-%s" (s-dashed-words (symbol-name interface))))
+ (&rest plist &key ,@(-map (-lambda ((key))
+ (intern (substring (symbol-name key) 1))) params)
+ &allow-other-keys)
+ (ignore ,@(-map (-lambda ((key))
+ (intern (substring (symbol-name key) 1))) params))
+ ,(format "Constructs %s from `plist.'
+Allowed params: %s" interface (reverse (-map #'cl-first params)))
+ ,(if lsp-use-plists
+ `(-mapcat (-lambda ((key value))
+ (list (or (cl-rest (assoc key ',params)) key) value))
+ (-partition 2 plist))
+ `(let (($$result (ht)))
+ (mapc (-lambda ((key value))
+ (puthash (lsp-keyword->string (or (cl-rest (assoc key ',params))
+ key))
+ value
+ $$result))
+ (-partition 2 plist))
+ $$result)))
+ `(pcase-defmacro ,interface (&rest property-bindings)
+ ,(if lsp-use-plists
+ ``(and
+ (pred listp)
+ ;; Check if all the types required by the
+ ;; interface exist in the expr-val.
+ ,@(-map
+ (lambda (key)
+ `(pred
+ (lambda (plist)
+ (plist-member plist ,key))))
+ ',required)
+ ;; Recursively generate the bindings.
+ ,@(let ((current-list property-bindings)
+ (output-bindings nil))
+ ;; Invariant: while current-list is
+ ;; non-nil, the car of current-list is
+ ;; always of the form :key, while the
+ ;; cadr of current-list is either a)
+ ;; nil, b) of the form :key-next or c)
+ ;; a pcase pattern that can
+ ;; recursively match an expression.
+ (while current-list
+ (-let* (((curr-binding-as-keyword next-entry . _) current-list)
+ (curr-binding-as-camelcased-symbol
+ (or (alist-get curr-binding-as-keyword ',params)
+ (error "Unknown key: %s. Available keys: %s"
+ (symbol-name curr-binding-as-keyword)
+ ',(-map #'cl-first params))))
+ (bound-name (lsp-keyword->symbol curr-binding-as-keyword))
+ (next-entry-is-key-or-nil
+ (and (symbolp next-entry)
+ (or (null next-entry)
+ (s-starts-with? ":" (symbol-name next-entry))))))
+ (cond
+ ;; If the next-entry is either a
+ ;; plist-key or nil, then bind to
+ ;; bound-name the value corresponding
+ ;; to the camelcased symbol. Pop
+ ;; current-list once.
+ (next-entry-is-key-or-nil
+ (push `(app (lambda (plist)
+ (plist-get plist ,curr-binding-as-camelcased-symbol))
+ ,bound-name)
+ output-bindings)
+ (setf current-list (cdr current-list)))
+ ;; Otherwise, next-entry is a pcase
+ ;; pattern we recursively match to the
+ ;; expression. This can in general
+ ;; create additional bindings that we
+ ;; persist in the top level of
+ ;; bindings. We pop current-list
+ ;; twice.
+ (t
+ (push `(app (lambda (plist)
+ (plist-get plist ,curr-binding-as-camelcased-symbol))
+ ,next-entry)
+ output-bindings)
+ (setf current-list (cddr current-list))))))
+ output-bindings))
+ ``(and
+ (pred ht?)
+ ,@(-map
+ (lambda (key)
+ `(pred
+ (lambda (hash-table)
+ (ht-contains? hash-table ,(lsp-keyword->string key)))))
+ ',required)
+ ,@(let ((current-list property-bindings)
+ (output-bindings nil))
+ (while current-list
+ (-let* (((curr-binding-as-keyword next-entry . _) current-list)
+ (curr-binding-as-camelcased-string
+ (lsp-keyword->string (or (alist-get curr-binding-as-keyword ',params)
+ (error "Unknown key: %s. Available keys: %s"
+ (symbol-name curr-binding-as-keyword)
+ ',(-map #'cl-first params)))))
+ (bound-name (lsp-keyword->symbol curr-binding-as-keyword))
+ (next-entry-is-key-or-nil
+ (and (symbolp next-entry)
+ (or (null next-entry)
+ (s-starts-with? ":" (symbol-name next-entry))))))
+ (cond
+ (next-entry-is-key-or-nil
+ (push `(app (lambda (hash-table)
+ (ht-get hash-table ,curr-binding-as-camelcased-string))
+ ,bound-name)
+ output-bindings)
+ (setf current-list (cdr current-list)))
+ (t
+ (push `(app (lambda (hash-table)
+ (ht-get hash-table ,curr-binding-as-camelcased-string))
+ ,next-entry)
+ output-bindings)
+ (setf current-list (cddr current-list))))))
+ output-bindings))))
+ (-mapcat (-lambda ((label . name))
+ (list
+ `(defun ,(intern (format "lsp:%s-%s"
+ (s-dashed-words (symbol-name interface))
+ (substring (symbol-name label) 1)))
+ (object)
+ ,(if lsp-use-plists
+ `(plist-get object ,name)
+ `(when (ht? object) (gethash ,(lsp-keyword->string name) object))))
+ `(defun ,(intern (format "lsp:set-%s-%s"
+ (s-dashed-words (symbol-name interface))
+ (substring (symbol-name label) 1)))
+ (object value)
+ ,@(if lsp-use-plists
+ `((plist-put object ,name value))
+ `((puthash ,(lsp-keyword->string name) value object)
+ object)))))
+ params)))))
+ (apply #'append)
+ (cl-list* 'progn))))
+
+(if lsp-use-plists
+ (progn
+ (defun lsp-get (from key)
+ (plist-get from key))
+ (defun lsp-put (where key value)
+ (plist-put where key value))
+ (defun lsp-map (fn value)
+ (-map (-lambda ((k v))
+ (funcall fn (lsp-keyword->string k) v))
+ (-partition 2 value )))
+ (defalias 'lsp-merge 'append)
+ (defalias 'lsp-empty? 'null)
+ (defalias 'lsp-copy 'copy-sequence)
+ (defun lsp-member? (from key)
+ (when (listp from)
+ (plist-member from key))))
+ (defun lsp-get (from key)
+ (when from
+ (gethash (lsp-keyword->string key) from)))
+ (defun lsp-put (where key value)
+ (prog1 where
+ (puthash (lsp-keyword->string key) value where)))
+ (defun lsp-map (fn value)
+ (when value
+ (maphash fn value)))
+ (defalias 'lsp-merge 'ht-merge)
+ (defalias 'lsp-empty? 'ht-empty?)
+ (defalias 'lsp-copy 'ht-copy)
+ (defun lsp-member? (from key)
+ (when (hash-table-p from)
+ (not (eq (gethash (lsp-keyword->string key) from :__lsp_default)
+ :__lsp_default)))))
+
+(defmacro lsp-defun (name match-form &rest body)
+ "Define a function named NAME.
+The function destructures its input as MATCH-FORM then executes BODY.
+
+Note that you have to enclose the MATCH-FORM in a pair of parens,
+such that:
+
+ (-defun (x) body)
+ (-defun (x y ...) body)
+
+has the usual semantics of `defun'. Furthermore, these get
+translated into a normal `defun', so there is no performance
+penalty.
+
+See `-let' for a description of the destructuring mechanism."
+ (declare (doc-string 3) (indent defun)
+ (debug (&define name sexp
+ [&optional stringp]
+ [&optional ("declare" &rest sexp)]
+ [&optional ("interactive" interactive)]
+ def-body)))
+ (cond
+ ((nlistp match-form)
+ (signal 'wrong-type-argument (list #'listp match-form)))
+ ;; no destructuring, so just return regular defun to make things faster
+ ((-all? #'symbolp match-form)
+ `(defun ,name ,match-form ,@body))
+ (t
+ (-let* ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index))) match-form))
+ ((body docs) (cond
+ ;; only docs
+ ((and (stringp (car body))
+ (not (cdr body)))
+ (list body (car body)))
+ ;; docs + body
+ ((stringp (car body))
+ (list (cdr body) (car body)))
+ ;; no docs
+ (t (list body))))
+ ((body interactive-form) (cond
+ ;; interactive form
+ ((and (listp (car body))
+ (eq (caar body) 'interactive))
+ (list (cdr body) (car body)))
+ ;; no interactive form
+ (t (list body)))))
+ ;; TODO: because inputs to the defun are evaluated only once,
+ ;; -let* need not to create the extra bindings to ensure that.
+ ;; We should find a way to optimize that. Not critical however.
+ `(defun ,name ,(-map #'cadr inputs)
+ ,@(when docs (list docs))
+ ,@(when interactive-form (list interactive-form))
+ (-let* ,inputs ,@body))))))
+
+
+
+
+;; manually defined interfaces
+(defconst lsp/markup-kind-plain-text "plaintext")
+(defconst lsp/markup-kind-markdown "markdown")
+
+(lsp-interface (JSONResponse (:params :id :method :result) nil)
+ (JSONResponseError (:error) nil)
+ (JSONMessage nil (:params :id :method :result :error))
+ (JSONResult nil (:params :id :method))
+ (JSONNotification (:params :method) nil)
+ (JSONRequest (:params :method) nil)
+ (JSONError (:message :code) (:data))
+ (ProgressParams (:token :value) nil)
+ (Edit (:kind) nil)
+ (WorkDoneProgress (:kind) nil)
+ (WorkDoneProgressBegin (:kind :title) (:cancellable :message :percentage))
+ (WorkDoneProgressReport (:kind) (:cancellable :message :percentage))
+ (WorkDoneProgressEnd (:kind) (:message))
+ (WorkDoneProgressOptions nil (:workDoneProgress))
+ (SemanticTokensOptions (:legend) (:rangeProvider :documentProvider))
+ (SemanticTokensLegend (:tokenTypes :tokenModifiers))
+ (SemanticTokensResult (:resultId) (:data))
+ (SemanticTokensPartialResult nil (:data))
+ (SemanticTokensEdit (:start :deleteCount) (:data))
+ (SemanticTokensDelta (:resultId) (:edits))
+ (SemanticTokensDeltaPartialResult nil (:edits)))
+
+(lsp-interface (v1:ProgressParams (:id :title) (:message :percentage :done)))
+
+(defun dash-expand:&RangeToPoint (key source)
+ "Convert the position KEY from SOURCE into a point."
+ `(lsp--position-to-point
+ (lsp-get ,source ,key)))
+
+(lsp-interface (eslint:StatusParams (:state) nil)
+ (eslint:OpenESLintDocParams (:url) nil)
+ (eslint:ConfirmExecutionParams (:scope :file :libraryPath) nil))
+
+(lsp-interface (haxe:ProcessStartNotification (:title) nil))
+
+(lsp-interface (pwsh:ScriptRegion (:StartLineNumber :EndLineNumber :StartColumnNumber :EndColumnNumber :Text) nil))
+
+(lsp-interface (omnisharp:ErrorMessage (:Text :FileName :Line :Column))
+ (omnisharp:ProjectInformationRequest (:FileName))
+ (omnisharp:MsBuildProject (:IsUnitProject :IsExe :Platform :Configuration :IntermediateOutputPath :OutputPath :TargetFrameworks :SourceFiles :TargetFramework :TargetPath :AssemblyName :Path :ProjectGuid))
+ (omnisharp:ProjectInformation (:ScriptProject :MsBuildProject))
+ (omnisharp:CodeStructureRequest (:FileName))
+ (omnisharp:CodeStructureResponse (:Elements))
+ (omnisharp:CodeElement (:Kind :Name :DisplayName :Children :Ranges :Properties))
+ (omnisharp:CodeElementProperties () (:static :accessibility :testMethodName :testFramework))
+ (omnisharp:Range (:Start :End))
+ (omnisharp:RangeList () (:attributes :full :name))
+ (omnisharp:Point (:Line :Column))
+ (omnisharp:RunTestsInClassRequest (:MethodNames :RunSettings :TestFrameworkname :TargetFrameworkVersion :NoBuild :Line :Column :Buffer :FileName))
+ (omnisharp:RunTestResponse (:Results :Pass :Failure :ContextHadNoTests))
+ (omnisharp:TestMessageEvent (:MessageLevel :Message))
+ (omnisharp:DotNetTestResult (:MethodName :Outcome :ErrorMessage :ErrorStackTrace :StandardOutput :StandardError)))
+
+(lsp-interface (rls:Cmd (:args :binary :env :cwd) nil))
+
+(defconst lsp/rust-analyzer-inlay-hint-kind-type-hint "TypeHint")
+(defconst lsp/rust-analyzer-inlay-hint-kind-param-hint "ParameterHint")
+(defconst lsp/rust-analyzer-inlay-hint-kind-chaining-hint "ChainingHint")
+(lsp-interface (rust-analyzer:AnalyzerStatusParams (:textDocument))
+ (rust-analyzer:SyntaxTreeParams (:textDocument) (:range))
+ (rust-analyzer:ExpandMacroParams (:textDocument :position) nil)
+ (rust-analyzer:ExpandedMacro (:name :expansion) nil)
+ (rust-analyzer:MatchingBraceParams (:textDocument :positions) nil)
+ (rust-analyzer:OpenCargoTomlParams (:textDocument) nil)
+ (rust-analyzer:ResovedCodeActionParams (:id :codeActionParams) nil)
+ (rust-analyzer:JoinLinesParams (:textDocument :ranges) nil)
+ (rust-analyzer:RunnablesParams (:textDocument) (:position))
+ (rust-analyzer:Runnable (:label :kind :args) (:location))
+ (rust-analyzer:RunnableArgs (:cargoArgs :executableArgs) (:workspaceRoot))
+ (rust-analyzer:RelatedTestsParams (:textDocument :position) nil)
+ (rust-analyzer:RelatedTests (:runnable) nil)
+ (rust-analyzer:InlayHint (:range :label :kind) nil)
+ (rust-analyzer:InlayHintsParams (:textDocument) nil)
+ (rust-analyzer:SsrParams (:query :parseOnly) nil)
+ (rust-analyzer:CommandLink (:title :command) (:arguments :tooltip))
+ (rust-analyzer:CommandLinkGroup (:commands) (:title)))
+
+
+;; begin autogenerated code
+
+(defvar lsp/completion-item-kind-lookup
+ [nil Text Method Function Constructor Field Variable Class Interface Module Property Unit Value Enum Keyword Snippet Color File Reference Folder EnumMember Constant Struct Event Operator TypeParameter])
+(defconst lsp/completion-item-kind-text 1)
+(defconst lsp/completion-item-kind-method 2)
+(defconst lsp/completion-item-kind-function 3)
+(defconst lsp/completion-item-kind-constructor 4)
+(defconst lsp/completion-item-kind-field 5)
+(defconst lsp/completion-item-kind-variable 6)
+(defconst lsp/completion-item-kind-class 7)
+(defconst lsp/completion-item-kind-interface 8)
+(defconst lsp/completion-item-kind-module 9)
+(defconst lsp/completion-item-kind-property 10)
+(defconst lsp/completion-item-kind-unit 11)
+(defconst lsp/completion-item-kind-value 12)
+(defconst lsp/completion-item-kind-enum 13)
+(defconst lsp/completion-item-kind-keyword 14)
+(defconst lsp/completion-item-kind-snippet 15)
+(defconst lsp/completion-item-kind-color 16)
+(defconst lsp/completion-item-kind-file 17)
+(defconst lsp/completion-item-kind-reference 18)
+(defconst lsp/completion-item-kind-folder 19)
+(defconst lsp/completion-item-kind-enum-member 20)
+(defconst lsp/completion-item-kind-constant 21)
+(defconst lsp/completion-item-kind-struct 22)
+(defconst lsp/completion-item-kind-event 23)
+(defconst lsp/completion-item-kind-operator 24)
+(defconst lsp/completion-item-kind-type-parameter 25)
+(defvar lsp/completion-trigger-kind-lookup
+ [nil Invoked TriggerCharacter TriggerForIncompleteCompletions])
+(defconst lsp/completion-trigger-kind-invoked 1)
+(defconst lsp/completion-trigger-kind-trigger-character 2)
+(defconst lsp/completion-trigger-kind-trigger-for-incomplete-completions 3)
+(defvar lsp/diagnostic-severity-lookup
+ [nil Error Warning Information Hint Max])
+(defconst lsp/diagnostic-severity-error 1)
+(defconst lsp/diagnostic-severity-warning 2)
+(defconst lsp/diagnostic-severity-information 3)
+(defconst lsp/diagnostic-severity-hint 4)
+(defconst lsp/diagnostic-severity-max 5)
+(defvar lsp/diagnostic-tag-lookup
+ [nil Unnecessary Deprecated])
+(defconst lsp/diagnostic-tag-unnecessary 1)
+(defconst lsp/diagnostic-tag-deprecated 2)
+(defvar lsp/document-highlight-kind-lookup
+ [nil Text Read Write])
+(defconst lsp/document-highlight-kind-text 1)
+(defconst lsp/document-highlight-kind-read 2)
+(defconst lsp/document-highlight-kind-write 3)
+(defvar lsp/file-change-type-lookup
+ [nil Created Changed Deleted])
+(defconst lsp/file-change-type-created 1)
+(defconst lsp/file-change-type-changed 2)
+(defconst lsp/file-change-type-deleted 3)
+(defvar lsp/insert-text-format-lookup
+ [nil PlainText Snippet])
+(defconst lsp/insert-text-format-plain-text 1)
+(defconst lsp/insert-text-format-snippet 2)
+(defvar lsp/insert-text-mode-lookup
+ [nil AsIs AdjustIndentation])
+(defconst lsp/insert-text-mode-as-it 1)
+(defconst lsp/insert-text-mode-adjust-indentation 2)
+(defvar lsp/message-type-lookup
+ [nil Error Warning Info Log])
+(defconst lsp/message-type-error 1)
+(defconst lsp/message-type-warning 2)
+(defconst lsp/message-type-info 3)
+(defconst lsp/message-type-log 4)
+(defvar lsp/signature-help-trigger-kind-lookup
+ [nil Invoked TriggerCharacter ContentChange])
+(defconst lsp/signature-help-trigger-kind-invoked 1)
+(defconst lsp/signature-help-trigger-kind-trigger-character 2)
+(defconst lsp/signature-help-trigger-kind-content-change 3)
+(defvar lsp/symbol-kind-lookup
+ [nil File Module Namespace Package Class Method Property Field Constructor Enum Interface Function Variable Constant String Number Boolean Array Object Key Null EnumMember Struct Event Operator TypeParameter])
+(defconst lsp/symbol-kind-file 1)
+(defconst lsp/symbol-kind-module 2)
+(defconst lsp/symbol-kind-namespace 3)
+(defconst lsp/symbol-kind-package 4)
+(defconst lsp/symbol-kind-class 5)
+(defconst lsp/symbol-kind-method 6)
+(defconst lsp/symbol-kind-property 7)
+(defconst lsp/symbol-kind-field 8)
+(defconst lsp/symbol-kind-constructor 9)
+(defconst lsp/symbol-kind-enum 10)
+(defconst lsp/symbol-kind-interface 11)
+(defconst lsp/symbol-kind-function 12)
+(defconst lsp/symbol-kind-variable 13)
+(defconst lsp/symbol-kind-constant 14)
+(defconst lsp/symbol-kind-string 15)
+(defconst lsp/symbol-kind-number 16)
+(defconst lsp/symbol-kind-boolean 17)
+(defconst lsp/symbol-kind-array 18)
+(defconst lsp/symbol-kind-object 19)
+(defconst lsp/symbol-kind-key 20)
+(defconst lsp/symbol-kind-null 21)
+(defconst lsp/symbol-kind-enum-member 22)
+(defconst lsp/symbol-kind-struct 23)
+(defconst lsp/symbol-kind-event 24)
+(defconst lsp/symbol-kind-operator 25)
+(defconst lsp/symbol-kind-type-parameter 26)
+(defvar lsp/text-document-save-reason-lookup
+ [nil Manual AfterDelay FocusOut])
+(defconst lsp/text-document-save-reason-manual 1)
+(defconst lsp/text-document-save-reason-after-delay 2)
+(defconst lsp/text-document-save-reason-focus-out 3)
+(defvar lsp/text-document-sync-kind-lookup
+ [None Full Incremental])
+(defconst lsp/text-document-sync-kind-none 0)
+(defconst lsp/text-document-sync-kind-full 1)
+(defconst lsp/text-document-sync-kind-incremental 2)
+(defvar lsp/type-hierarchy-direction-lookup
+ [nil Children Parents Both])
+(defconst lsp/type-hierarchy-direction-children 1)
+(defconst lsp/type-hierarchy-direction-parents 2)
+(defconst lsp/type-hierarchy-direction-both 3)
+(defvar lsp/call-hierarchy-direction-lookup
+ [nil CallsFrom CallsTo])
+(defconst lsp/call-hierarchy-direction-calls-from 1)
+(defconst lsp/call-hierarchy-direction-calls-to 2)
+(defvar lsp/response-error-code-lookup
+ [nil ParseError InvalidRequest MethodNotFound InvalidParams InternalError serverErrorStart serverErrorEnd])
+(defconst lsp/response-error-code-parse-error 1)
+(defconst lsp/response-error-code-invalid-request 2)
+(defconst lsp/response-error-code-method-not-found 3)
+(defconst lsp/response-error-code-invalid-params 4)
+(defconst lsp/response-error-code-internal-error 5)
+(defconst lsp/response-error-code-server-error-start 6)
+(defconst lsp/response-error-code-server-error-end 7)
+
+(lsp-interface
+ (CallHierarchyCapabilities nil (:dynamicRegistration))
+ (CallHierarchyItem (:kind :name :range :selectionRange :uri) (:detail :tags))
+ (ClientCapabilities nil (:experimental :textDocument :workspace))
+ (ClientInfo (:name) (:version))
+ (CodeActionCapabilities nil (:codeActionLiteralSupport :dynamicRegistration :isPreferredSupport :dataSupport :resolveSupport))
+ (CodeActionContext (:diagnostics) (:only))
+ (CodeActionKindCapabilities (:valueSet) nil)
+ (CodeActionLiteralSupportCapabilities nil (:codeActionKind))
+ (CodeActionOptions nil (:codeActionKinds :resolveProvider))
+ (CodeLensCapabilities nil (:dynamicRegistration))
+ (CodeLensOptions (:resolveProvider) nil)
+ (Color (:red :green :blue :alpha) nil)
+ (ColorProviderCapabilities nil (:dynamicRegistration))
+ (ColorProviderOptions nil (:documentSelector :id))
+ (ColoringInformation (:range :styles) nil)
+ (Command (:title :command) (:arguments))
+ (CompletionCapabilities nil (:completionItem :completionItemKind :contextSupport :dynamicRegistration))
+ (CompletionContext (:triggerKind) (:triggerCharacter))
+ (CompletionItem (:label) (:additionalTextEdits :command :commitCharacters :data :deprecated :detail :documentation :filterText :insertText :insertTextFormat :insertTextMode :kind :preselect :sortText :tags :textEdit :score))
+ (CompletionItemCapabilities nil (:commitCharactersSupport :deprecatedSupport :documentationFormat :preselectSupport :snippetSupport :tagSupport :insertReplaceSupport :resolveSupport))
+ (CompletionItemKindCapabilities nil (:valueSet))
+ (CompletionItemTagSupportCapabilities (:valueSet) nil)
+ (CompletionOptions nil (:resolveProvider :triggerCharacters :allCommitCharacters))
+ (ConfigurationItem nil (:scopeUri :section))
+ (CreateFileOptions nil (:ignoreIfExists :overwrite))
+ (DeclarationCapabilities nil (:dynamicRegistration :linkSupport))
+ (DefinitionCapabilities nil (:dynamicRegistration :linkSupport))
+ (DeleteFileOptions nil (:ignoreIfNotExists :recursive))
+ (Diagnostic (:range :message) (:code :relatedInformation :severity :source :tags))
+ (DiagnosticRelatedInformation (:location :message) nil)
+ (DiagnosticsTagSupport (:valueSet) nil)
+ (DidChangeConfigurationCapabilities nil (:dynamicRegistration))
+ (DidChangeWatchedFilesCapabilities nil (:dynamicRegistration))
+ (DocumentFilter nil (:language :pattern :scheme))
+ (DocumentHighlightCapabilities nil (:dynamicRegistration))
+ (DocumentLinkCapabilities nil (:dynamicRegistration :tooltipSupport))
+ (DocumentLinkOptions nil (:resolveProvider))
+ (DocumentOnTypeFormattingOptions (:firstTriggerCharacter) (:moreTriggerCharacter))
+ (DocumentSymbol (:kind :name :range :selectionRange) (:children :deprecated :detail))
+ (DocumentSymbolCapabilities nil (:dynamicRegistration :hierarchicalDocumentSymbolSupport :symbolKind))
+ (ExecuteCommandCapabilities nil (:dynamicRegistration))
+ (ExecuteCommandOptions (:commands) nil)
+ (FileEvent (:type :uri) nil)
+ (FileSystemWatcher (:globPattern) (:kind))
+ (FoldingRangeCapabilities nil (:dynamicRegistration :lineFoldingOnly :rangeLimit))
+ (FoldingRangeProviderOptions nil (:documentSelector :id))
+ (FormattingCapabilities nil (:dynamicRegistration))
+ (FormattingOptions (:tabSize :insertSpaces) (:trimTrailingWhitespace :insertFinalNewline :trimFinalNewlines))
+ (HoverCapabilities nil (:contentFormat :dynamicRegistration))
+ (ImplementationCapabilities nil (:dynamicRegistration :linkSupport))
+ (Location (:range :uri) nil)
+ (MarkedString (:language :value) nil)
+ (MarkupContent (:kind :value) nil)
+ (MessageActionItem (:title) nil)
+ (OnTypeFormattingCapabilities nil (:dynamicRegistration))
+ (ParameterInformation (:label) (:documentation))
+ (ParameterInformationCapabilities nil (:labelOffsetSupport))
+ (Position (:character :line) nil)
+ (PublishDiagnosticsCapabilities nil (:relatedInformation :tagSupport :versionSupport))
+ (Range (:start :end) nil)
+ (RangeFormattingCapabilities nil (:dynamicRegistration))
+ (ReferenceContext (:includeDeclaration) nil)
+ (ReferencesCapabilities nil (:dynamicRegistration))
+ (Registration (:method :id) (:registerOptions))
+ (RenameCapabilities nil (:dynamicRegistration :prepareSupport))
+ (RenameFileOptions nil (:ignoreIfExists :overwrite))
+ (RenameOptions nil (:documentSelector :id :prepareProvider))
+ (ResourceChange nil (:current :newUri))
+ (ResourceOperation (:kind) nil)
+ (SaveOptions nil (:includeText))
+ (SelectionRange (:range) (:parent))
+ (SelectionRangeCapabilities nil (:dynamicRegistration))
+ (SemanticHighlightingCapabilities nil (:semanticHighlighting))
+ (SemanticHighlightingInformation (:line) (:tokens))
+ (SemanticHighlightingServerCapabilities nil (:scopes))
+ (ServerCapabilities nil (:callHierarchyProvider :codeActionProvider :codeLensProvider :colorProvider :completionProvider :declarationProvider :definitionProvider :documentFormattingProvider :documentHighlightProvider :documentLinkProvider :documentOnTypeFormattingProvider :documentRangeFormattingProvider :documentSymbolProvider :executeCommandProvider :experimental :foldingRangeProvider :hoverProvider :implementationProvider :referencesProvider :renameProvider :selectionRangeProvider :semanticHighlighting :signatureHelpProvider :textDocumentSync :typeDefinitionProvider :typeHierarchyProvider :workspace :workspaceSymbolProvider :semanticTokensProvider))
+ (ServerInfo (:name) (:version))
+ (SignatureHelp (:signatures) (:activeParameter :activeSignature))
+ (SignatureHelpCapabilities nil (:contextSupport :dynamicRegistration :signatureInformation))
+ (SignatureHelpContext (:triggerKind :isRetrigger) (:activeSignatureHelp :triggerCharacter))
+ (SignatureHelpOptions nil (:retriggerCharacters :triggerCharacters))
+ (SignatureInformation (:label) (:documentation :parameters))
+ (SignatureInformationCapabilities nil (:documentationFormat :parameterInformation))
+ (StaticRegistrationOptions nil (:documentSelector :id))
+ (SymbolCapabilities nil (:dynamicRegistration :symbolKind))
+ (SymbolKindCapabilities nil (:valueSet))
+ (SynchronizationCapabilities nil (:didSave :dynamicRegistration :willSave :willSaveWaitUntil))
+ (TextDocumentClientCapabilities nil (:callHierarchy :codeAction :codeLens :colorProvider :completion :declaration :definition :documentHighlight :documentLink :documentSymbol :foldingRange :formatting :hover :implementation :onTypeFormatting :publishDiagnostics :rangeFormatting :references :rename :selectionRange :semanticHighlightingCapabilities :signatureHelp :synchronization :typeDefinition :typeHierarchyCapabilities))
+ (TextDocumentContentChangeEvent (:text) (:range :rangeLength))
+ (TextDocumentEdit (:textDocument :edits) nil)
+ (TextDocumentIdentifier (:uri) nil)
+ (TextDocumentItem (:languageId :text :uri :version) nil)
+ (TextDocumentSyncOptions nil (:change :openClose :save :willSave :willSaveWaitUntil))
+ (TextEdit (:newText :range) nil)
+ (InsertReplaceEdit (:newText :insert :replace) nil)
+ (SnippetTextEdit (:newText :range) (:insertTextFormat))
+ (TypeDefinitionCapabilities nil (:dynamicRegistration :linkSupport))
+ (TypeHierarchyCapabilities nil (:dynamicRegistration))
+ (TypeHierarchyItem (:kind :name :range :selectionRange :uri) (:children :data :deprecated :detail :parents))
+ (Unregistration (:method :id) nil)
+ (VersionedTextDocumentIdentifier (:uri) (:version))
+ (WorkspaceClientCapabilities nil (:applyEdit :configuration :didChangeConfiguration :didChangeWatchedFiles :executeCommand :symbol :workspaceEdit :workspaceFolders))
+ (WorkspaceEdit nil (:changes :documentChanges :resourceChanges))
+ (WorkspaceEditCapabilities nil (:documentChanges :failureHandling :resourceChanges :resourceOperations))
+ (WorkspaceFolder (:uri :name) nil)
+ (WorkspaceFoldersChangeEvent (:removed :added) nil)
+ (WorkspaceFoldersOptions nil (:changeNotifications :supported))
+ (WorkspaceServerCapabilities nil (:workspaceFolders))
+ (ApplyWorkspaceEditParams (:edit) (:label))
+ (ApplyWorkspaceEditResponse (:applied) nil)
+ (CallHierarchyIncomingCall (:from :fromRanges) nil)
+ (CallHierarchyIncomingCallsParams (:item) nil)
+ (CallHierarchyOutgoingCall (:to :fromRanges) nil)
+ (CallHierarchyOutgoingCallsParams (:item) nil)
+ (CallHierarchyPrepareParams (:textDocument :position) (:uri))
+ (CodeAction (:title) (:command :diagnostics :edit :isPreferred :kind :data))
+ (CodeActionKind nil nil)
+ (CodeActionParams (:textDocument :context :range) nil)
+ (CodeLens (:range) (:command :data))
+ (CodeLensParams (:textDocument) nil)
+ (CodeLensRegistrationOptions nil (:documentSelector :resolveProvider))
+ (ColorInformation (:color :range) nil)
+ (ColorPresentation (:label) (:additionalTextEdits :textEdit))
+ (ColorPresentationParams (:color :textDocument :range) nil)
+ (ColoringParams (:uri :infos) nil)
+ (ColoringStyle nil nil)
+ (CompletionList (:items :isIncomplete) nil)
+ (CompletionParams (:textDocument :position) (:context :uri))
+ (CompletionRegistrationOptions nil (:documentSelector :resolveProvider :triggerCharacters))
+ (ConfigurationParams (:items) nil)
+ (CreateFile (:kind :uri) (:options))
+ (DeclarationParams (:textDocument :position) (:uri))
+ (DefinitionParams (:textDocument :position) (:uri))
+ (DeleteFile (:kind :uri) (:options))
+ (DidChangeConfigurationParams (:settings) nil)
+ (DidChangeTextDocumentParams (:contentChanges :textDocument) (:uri))
+ (DidChangeWatchedFilesParams (:changes) nil)
+ (DidChangeWatchedFilesRegistrationOptions (:watchers) nil)
+ (DidChangeWorkspaceFoldersParams (:event) nil)
+ (DidCloseTextDocumentParams (:textDocument) nil)
+ (DidOpenTextDocumentParams (:textDocument) (:text))
+ (DidSaveTextDocumentParams (:textDocument) (:text))
+ (DocumentColorParams (:textDocument) nil)
+ (DocumentFormattingParams (:textDocument :options) nil)
+ (DocumentHighlight (:range) (:kind))
+ (DocumentHighlightParams (:textDocument :position) (:uri))
+ (DocumentLink (:range) (:data :target :tooltip))
+ (DocumentLinkParams (:textDocument) nil)
+ (DocumentLinkRegistrationOptions nil (:documentSelector :resolveProvider))
+ (DocumentOnTypeFormattingParams (:ch :textDocument :options :position) nil)
+ (DocumentOnTypeFormattingRegistrationOptions (:firstTriggerCharacter) (:documentSelector :moreTriggerCharacter))
+ (DocumentRangeFormattingParams (:textDocument :options :range) nil)
+ (DocumentSymbolParams (:textDocument) nil)
+ (DynamicRegistrationCapabilities nil (:dynamicRegistration))
+ (ExecuteCommandParams (:command) (:arguments))
+ (ExecuteCommandRegistrationOptions (:commands) nil)
+ (FailureHandlingKind nil nil)
+ (FoldingRange (:endLine :startLine) (:endCharacter :kind :startCharacter))
+ (FoldingRangeKind nil nil)
+ (FoldingRangeRequestParams (:textDocument) nil)
+ (Hover (:contents) (:range))
+ (HoverParams (:textDocument :position) (:uri))
+ (ImplementationParams (:textDocument :position) (:uri))
+ (InitializeError (:retry) nil)
+ (InitializeErrorCode nil nil)
+ (InitializeParams nil (:capabilities :clientInfo :clientName :initializationOptions :processId :rootPath :rootUri :trace :workspaceFolders))
+ (InitializeResult (:capabilities) (:serverInfo))
+ (InitializedParams nil nil)
+ (LocationLink (:targetSelectionRange :targetUri :targetRange) (:originSelectionRange))
+ (MarkupKind nil nil)
+ (MessageParams (:type :message) nil)
+ (PrepareRenameParams (:textDocument :position) (:uri))
+ (PrepareRenameResult (:range :placeholder) nil)
+ (PublishDiagnosticsParams (:diagnostics :uri) (:version))
+ (ReferenceParams (:textDocument :context :position) (:uri))
+ (RegistrationParams (:registrations) nil)
+ (RenameFile (:kind :newUri :oldUri) (:options))
+ (RenameParams (:newName :textDocument :position) (:uri))
+ (ResolveTypeHierarchyItemParams (:item :resolve :direction) nil)
+ (ResourceOperationKind nil nil)
+ (SelectionRangeParams (:textDocument :positions) nil)
+ (SemanticHighlightingParams (:textDocument :lines) nil)
+ (ShowMessageRequestParams (:type :message) (:actions))
+ (SignatureHelpParams (:textDocument :position) (:context :uri))
+ (SignatureHelpRegistrationOptions nil (:documentSelector :triggerCharacters))
+ (SymbolInformation (:kind :name :location) (:containerName :deprecated))
+ (TextDocumentChangeRegistrationOptions (:syncKind) (:documentSelector))
+ (TextDocumentPositionParams (:textDocument :position) (:uri))
+ (TextDocumentRegistrationOptions nil (:documentSelector))
+ (TextDocumentSaveRegistrationOptions nil (:documentSelector :includeText))
+ (TypeDefinitionParams (:textDocument :position) (:uri))
+ (TypeHierarchyParams (:resolve :textDocument :position) (:direction :uri))
+ (UnregistrationParams (:unregisterations) nil)
+ (WatchKind nil nil)
+ (WillSaveTextDocumentParams (:reason :textDocument) nil)
+ (WorkspaceSymbolParams (:query) nil))
+
+
+(provide 'lsp-protocol)
+
+;;; lsp-protocol.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-purescript.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-purescript.el
new file mode 100644
index 0000000..d6e761a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-purescript.el
@@ -0,0 +1,72 @@
+;;; lsp-purescript.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, purescript
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the PureScript Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-purescript nil
+ "LSP support for PureScript, using purescript-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/nwolverson/purescript-language-server"))
+
+(defcustom lsp-purescript-server-executable nil
+ "Path to server executable."
+ :type 'string
+ :risky t
+ :group 'lsp-purescript)
+
+(defcustom lsp-purescript-server-args
+ '("--stdio")
+ "Arguments to pass to the server."
+ :type '(repeat string)
+ :risky t
+ :group 'lsp-purescript)
+
+(defun lsp-purescript--server-command ()
+ "Generate LSP startup command for purescript-language-server."
+ (cons (or lsp-purescript-server-executable
+ (lsp-package-path 'purescript-language-server))
+ lsp-purescript-server-args))
+
+(lsp-dependency 'purescript-language-server
+ '(:system "purescript-language-server")
+ '(:npm :package "purescript-language-server"
+ :path "purescript-language-server"))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ #'lsp-purescript--server-command)
+ :major-modes '(purescript-mode)
+ :priority -1
+ :server-id 'pursls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'purescript-language-server callback error-callback))))
+
+
+(lsp-consistency-check lsp-purescript)
+
+(provide 'lsp-purescript)
+;;; lsp-purescript.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pwsh.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pwsh.el
new file mode 100644
index 0000000..0e90164
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pwsh.el
@@ -0,0 +1,360 @@
+;;; lsp-pwsh.el --- client for PowerShellEditorServices -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Kien Nguyen
+
+;; Author: kien.n.quang at gmail.com
+;; Keywords: lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'f)
+(require 'dash)
+(require 's)
+(require 'ht)
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defgroup lsp-pwsh nil
+ "LSP support for PowerShell, using the PowerShellEditorServices."
+ :group 'lsp-mode
+ :package-version '(lsp-mode . "6.2"))
+
+;; PowerShell vscode flags
+(defcustom lsp-pwsh-help-completion "BlockComment"
+ "Controls the comment-based help completion behavior triggered by typing '##'.
+Set the generated help style with 'BlockComment' or 'LineComment'.
+Disable the feature with 'Disabled'."
+ :type
+ '(choice
+ (:tag "Disabled" "BlockComment" "LineComment"))
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-script-analysis-enable t
+ "Enables real-time script analysis from PowerShell Script Analyzer.
+Uses the newest installed version of the PSScriptAnalyzer module or the
+version bundled with this extension, if it is newer."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-script-analysis-settings-path ""
+ "Specifies the path to a PowerShell Script Analyzer settings file.
+To override the default settings for all projects, enter an absolute path,
+or enter a path relative to your workspace."
+ :type 'string
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-folding-enable t
+ "Enables syntax based code folding.
+When disabled, the default indentation based code folding is used."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-folding-show-last-line t
+ "Shows the last line of a folded section.
+Similar to the default VSCode folding style.
+When disabled, the entire folded region is hidden."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-preset "Custom"
+ "Sets the codeformatting options to follow the given indent style.
+Sets in a way that is compatible with PowerShell syntax.
+For more information about the brace styles please refer to https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81."
+ :type
+ '(choice
+ (:tag "Custom" "Allman" "OTBS" "Stroustrup"))
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-open-brace-on-same-line t
+ "Places open brace on the same line as its associated statement."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-new-line-after-open-brace t
+ "Adds a newline (line break) after an open brace."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-new-line-after-close-brace t
+ "Adds a newline (line break) after a closing brace."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-pipeline-indentation-style "NoIndentation"
+ "Multi-line pipeline style settings."
+ :type
+ '(choice
+ (:tag "IncreaseIndentationForFirstPipeline" "IncreaseIndentationAfterEveryPipeline" "NoIndentation"))
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-before-open-brace t
+ "Adds a space between a keyword and its associated scriptblock expression."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-before-open-paren t
+ "Adds a space between a keyword (if, elseif, while, switch, etc) and its
+associated conditional expression."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-around-operator t
+ "Adds spaces before and after an operator ('=', '+', '-', etc.)."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-after-separator t
+ "Adds a space after a separator (',' and ';')."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-inside-brace t
+ "Adds a space after an opening brace ('{') and before a closing brace ('}')."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-whitespace-around-pipe t
+ "Adds a space before and after the pipeline operator ('|')."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-ignore-one-line-block t
+ "Does not reformat one-line code blocks, such as \"if (...) {...} else
+{...}\"."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-align-property-value-pairs t
+ "Align assignment statements in a hashtable or a DSC Configuration."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-code-formatting-use-correct-casing nil
+ "Use correct casing for cmdlets."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-developer-editor-services-log-level "Normal"
+ "Sets the log level for the PowerShell Editor Services host executable.
+Valid values are 'Diagnostic', 'Verbose', 'Normal', 'Warning', and 'Error'"
+ :type
+ '(choice
+ (:tag "Diagnostic" "Verbose" "Normal" "Warning" "Error"))
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-developer-editor-services-wait-for-debugger nil
+ "Launches the language service with the /waitForDebugger flag to force it to
+wait for a .NET debugger to attach before proceeding."
+ :type 'boolean
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-developer-feature-flags nil
+ "An array of strings that enable experimental features in the PowerShell
+extension."
+ :type
+ '(repeat string)
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(lsp-register-custom-settings
+ '(("powershell.developer.featureFlags" lsp-pwsh-developer-feature-flags)
+ ("powershell.developer.editorServicesWaitForDebugger" lsp-pwsh-developer-editor-services-wait-for-debugger t)
+ ("powershell.codeFormatting.useCorrectCasing" lsp-pwsh-code-formatting-use-correct-casing t)
+ ("powershell.codeFormatting.alignPropertyValuePairs" lsp-pwsh-code-formatting-align-property-value-pairs t)
+ ("powershell.codeFormatting.ignoreOneLineBlock" lsp-pwsh-code-formatting-ignore-one-line-block t)
+ ("powershell.codeFormatting.whitespaceAroundPipe" lsp-pwsh-code-formatting-whitespace-around-pipe t)
+ ("powershell.codeFormatting.whitespaceInsideBrace" lsp-pwsh-code-formatting-whitespace-inside-brace t)
+ ("powershell.codeFormatting.whitespaceAfterSeparator" lsp-pwsh-code-formatting-whitespace-after-separator t)
+ ("powershell.codeFormatting.whitespaceAroundOperator" lsp-pwsh-code-formatting-whitespace-around-operator t)
+ ("powershell.codeFormatting.whitespaceBeforeOpenParen" lsp-pwsh-code-formatting-whitespace-before-open-paren t)
+ ("powershell.codeFormatting.whitespaceBeforeOpenBrace" lsp-pwsh-code-formatting-whitespace-before-open-brace t)
+ ("powershell.codeFormatting.pipelineIndentationStyle" lsp-pwsh-code-formatting-pipeline-indentation-style)
+ ("powershell.codeFormatting.newLineAfterCloseBrace" lsp-pwsh-code-formatting-new-line-after-close-brace t)
+ ("powershell.codeFormatting.newLineAfterOpenBrace" lsp-pwsh-code-formatting-new-line-after-open-brace t)
+ ("powershell.codeFormatting.openBraceOnSameLine" lsp-pwsh-code-formatting-open-brace-on-same-line t)
+ ("powershell.codeFormatting.preset" lsp-pwsh-code-formatting-preset)
+ ("powershell.codeFolding.showLastLine" lsp-pwsh-code-folding-show-last-line t)
+ ("powershell.codeFolding.enable" lsp-pwsh-code-folding-enable t)
+ ("powershell.scriptAnalysis.settingsPath" lsp-pwsh-script-analysis-settings-path)
+ ("powershell.scriptAnalysis.enable" lsp-pwsh-script-analysis-enable t)
+ ("powershell.helpCompletion" lsp-pwsh-help-completion)))
+
+;; lsp-pwsh custom variables
+(defcustom lsp-pwsh-ext-path (f-join lsp-server-install-dir "pwsh")
+ "The path to powershell vscode extension."
+ :type 'string
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-exe (or (executable-find "pwsh") (executable-find "powershell"))
+ "PowerShell executable."
+ :type 'string
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pwsh-dir (expand-file-name "PowerShellEditorServices" lsp-pwsh-ext-path)
+ "Path to PowerShellEditorServices without last slash."
+ :type 'string
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defvar lsp-pwsh-log-path (expand-file-name "logs" lsp-pwsh-ext-path)
+ "Path to directory where server will write log files.
+Must not nil.")
+
+(defvar lsp-pwsh--sess-id (emacs-pid))
+
+(defun lsp-pwsh--command ()
+ "Return the command to start server."
+
+ `(,lsp-pwsh-exe "-NoProfile" "-NonInteractive" "-NoLogo"
+ ,@(if (eq system-type 'windows-nt) '("-ExecutionPolicy" "Bypass"))
+ "-OutputFormat" "Text"
+ "-File"
+ ,(f-join lsp-pwsh-dir "PowerShellEditorServices/Start-EditorServices.ps1")
+ "-HostName" "\"Emacs Host\""
+ "-HostProfileId" "'Emacs.LSP'"
+ "-HostVersion" "0.1"
+ "-LogPath" ,(f-join lsp-pwsh-log-path "emacs-powershell.log")
+ "-LogLevel" ,lsp-pwsh-developer-editor-services-log-level
+ "-SessionDetailsPath"
+ ,(format "%s/PSES-VSCode-%d" lsp-pwsh-log-path lsp-pwsh--sess-id)
+ ;; "-AdditionalModules" "@('PowerShellEditorServices.VSCode')"
+ "-Stdio"
+ "-BundledModulesPath" ,lsp-pwsh-dir
+ "-FeatureFlags" "@()"))
+
+(defun lsp-pwsh--extra-init-params ()
+ "Return form describing parameters for language server.")
+
+(lsp-defun lsp-pwsh--apply-code-action-edits ((&Command :command :arguments?))
+ "Handle ACTION for PowerShell.ApplyCodeActionEdits."
+ (-if-let* (((&pwsh:ScriptRegion :start-line-number :end-line-number
+ :start-column-number :end-column-number :text)
+ (lsp-seq-first arguments?))
+ (start-position (lsp-make-position :line (1- start-line-number)
+ :character (1- start-column-number)))
+ (end-position (lsp-make-position :line (1- end-line-number)
+ :character (1- end-column-number)))
+ (edits `[,(lsp-make-text-edit :range (lsp-make-range :start start-position
+ :end end-position)
+ :newText text)]))
+ (lsp--apply-text-edits edits 'code-action)
+ (lsp-send-execute-command command arguments?)))
+
+(lsp-defun lsp-pwsh--show-code-action-document ((&Command :arguments?))
+ "Handle ACTION for PowerShell.ShowCodeActionDocumentation."
+ (-if-let* ((rule-raw (lsp-seq-first arguments?))
+ (rule-id (if (s-prefix-p "PS" rule-raw) (substring rule-raw 2) rule-raw)))
+ (browse-url
+ (concat "https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/"
+ rule-id
+ ".md"))
+ (lsp-warn "Cannot show documentation for code action, no ruleName was supplied")))
+
+(defvar lsp-pwsh--major-modes '(powershell-mode))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-pwsh--command
+ (lambda ()
+ (f-exists? lsp-pwsh-dir)))
+ :major-modes lsp-pwsh--major-modes
+ :server-id 'pwsh-ls
+ :priority -1
+ :multi-root t
+ :initialization-options #'lsp-pwsh--extra-init-params
+ :notification-handlers (ht ("powerShell/executionStatusChanged" #'ignore)
+ ("output" #'ignore))
+ :action-handlers (ht ("PowerShell.ApplyCodeActionEdits"
+ #'lsp-pwsh--apply-code-action-edits)
+ ("PowerShell.ShowCodeActionDocumentation"
+ #'lsp-pwsh--show-code-action-document))
+ :initialized-fn (lambda (w)
+ (with-lsp-workspace w
+ (lsp--set-configuration
+ (lsp-configuration-section "powershell")))
+ (let ((caps (lsp--workspace-server-capabilities w)))
+ (lsp:set-server-capabilities-document-range-formatting-provider? caps t)
+ (lsp:set-server-capabilities-document-formatting-provider? caps t)))
+ :download-server-fn #'lsp-pwsh-setup))
+
+(defcustom lsp-pwsh-github-asset-url
+ "https://github.com/%s/%s/releases/latest/download/%s"
+ "GitHub latest asset template url."
+ :type 'string
+ :group 'lsp-pwsh
+ :package-version '(lsp-mode . "6.2"))
+
+(defun lsp-pwsh-setup (_client callback error-callback update)
+ "Downloads PowerShellEditorServices to `lsp-pwsh-dir'.
+CALLBACK is called when the download finish successfully otherwise
+ERROR-CALLBACK is called.
+UPDATE is non-nil if it is already downloaded.
+FORCED if specified with prefix argument."
+
+ (unless (and lsp-pwsh-exe (file-executable-p lsp-pwsh-exe))
+ (user-error "Use `lsp-pwsh-exe' with the value of `%s' is not a valid powershell binary"
+ lsp-pwsh-exe))
+
+ (let ((url (format lsp-pwsh-github-asset-url "PowerShell"
+ "PowerShellEditorServices" "PowerShellEditorServices.zip"))
+ (temp-file (make-temp-file "ext" nil ".zip")))
+ (unless (f-exists? lsp-pwsh-log-path)
+ (mkdir lsp-pwsh-log-path 'create-parent))
+ (unless (and (not update) (f-exists? lsp-pwsh-dir))
+ ;; since we know it's installed, use powershell to download the file
+ ;; (and avoid url.el bugginess or additional libraries)
+ (when (f-exists? lsp-pwsh-dir) (delete-directory lsp-pwsh-dir 'recursive))
+ (lsp-async-start-process
+ callback
+ error-callback
+ lsp-pwsh-exe "-noprofile" "-noninteractive" "-nologo"
+ "-ex" "bypass" "-command"
+ "Invoke-WebRequest" "-UseBasicParsing" "-uri" url "-outfile" temp-file ";"
+ "Expand-Archive" "-Path" temp-file
+ "-DestinationPath" (file-name-directory lsp-pwsh-dir)))))
+
+(lsp-consistency-check lsp-pwsh)
+
+(provide 'lsp-pwsh)
+;;; lsp-pwsh.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pyls.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pyls.el
new file mode 100644
index 0000000..20a4524
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pyls.el
@@ -0,0 +1,504 @@
+;;; lsp-pyls.el --- pyls configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; PYLS configuration
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-pyls nil
+ "LSP support for Python, using Palantir's Python Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/palantir/python-language-server")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-clients-python-library-directories '("/usr/")
+ "List of directories which will be considered to be libraries."
+ :risky t
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(define-obsolete-variable-alias
+ 'lsp-clients-python-command
+ 'lsp-pyls-server-command
+ "6.1")
+
+(defcustom lsp-pyls-disable-warning nil
+ "Disable Palantir python-language-server deprecation warning"
+ :group 'lsp-pyls
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-pyls-server-command '("pyls")
+ "Command to start pyls."
+ :risky t
+ :group 'lsp-pyls
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-configuration-sources ["pycodestyle"]
+ "List of configuration sources to use."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-completion-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-completion-include-params t
+ "Auto-completes methods and classes with tabstops for each
+parameter."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-definition-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-definition-follow-imports t
+ "The goto call will follow imports."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-definition-follow-builtin-imports t
+ "If follow_imports is True will decide if it follow builtin
+imports."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-hover-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-references-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-signature-help-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-symbols-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-jedi-symbols-all-scopes t
+ "If True lists the names of all scopes instead of only the
+module namespace."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-mccabe-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-mccabe-threshold 15
+ "The minimum threshold that triggers warnings about cyclomatic
+complexity."
+ :type 'number
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-preload-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-preload-modules nil
+ "List of modules to import on startup"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pylint-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pylint-args []
+ "Arguments, passed to pylint"
+ :risky t
+ :type 'lsp-string-vector
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-exclude nil
+ "Exclude files or directories which match these patterns."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-filename nil
+ "When parsing directories, only check filenames matching these
+patterns."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-select nil
+ "Select errors and warnings"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-ignore nil
+ "Ignore errors and warnings"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-hang-closing nil
+ "Hang closing bracket instead of matching indentation of
+opening bracket's line."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pycodestyle-max-line-length nil
+ "Set maximum allowed line length."
+ :type 'number
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-convention nil
+ "Choose the basic list of checked errors by specifying an
+existing convention."
+ :type '(choice (:tag "pep257" "numpy"))
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-add-ignore nil
+ "Ignore errors and warnings in addition to the specified
+convention."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-add-select nil
+ "Select errors and warnings in addition to the specified
+convention."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-ignore nil
+ "Ignore errors and warnings"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-select nil
+ "Select errors and warnings"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-match "(?!test_).*\\.py"
+ "Check only files that exactly match the given regular
+expression; default is to match files that don't start with
+'test_' but end with '.py'."
+ :type 'string
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pydocstyle-match-dir "[^\\.].*"
+ "Search only dirs that exactly match the given regular
+expression; default is to match dirs which do not begin with a
+dot."
+ :type 'string
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-pyflakes-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-rope-completion-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-autopep8-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-yapf-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-rope-extension-modules nil
+ "Builtin and c-extension modules that are allowed to be
+imported and inspected by rope."
+ :type 'string
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-rope-rope-folder nil
+ "The name of the folder in which rope stores project
+configurations and data. Pass `nil` for not using such a folder
+at all."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-pyls-plugins-flake8-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-exclude nil
+ "List of glob patterns to exclude from checks."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-filename nil
+ "List of glob patterns to include for checks."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-hang-closing nil
+ "Toggle whether pycodestyle should enforce matching the indentation of the
+opening bracket’s line. When you specify this, it will prefer that you hang the
+closing bracket rather than match the indentation."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-ignore nil
+ "A list of codes to ignore."
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-max-line-length nil
+ "Set the maximum length that any line (with some exceptions) may be.
+Exceptions include lines that are either strings or comments which are
+entirely URLs."
+ :type 'integer
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-select nil
+ "Specify the list of error codes you wish Flake8 to report. Similarly to
+`lsp-pyls-plugins-flake8-ignore'. You can specify a portion of an error code to
+get all that start with that string. For example, you can use E, E4, E43, and
+E431"
+ :type '(repeat string)
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-pyls-plugins-flake8-config nil
+ "A path to a config file that will be the only config file read and used.
+This will cause Flake8 to ignore all other config files that exist.
+
+NOTE: other parameters as `lsp-pyls-plugins-flake8-max-line-length' take
+precedence over parameters referenced in config."
+ :type 'string
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-pyls-plugins-jedi-use-pyenv-environment nil
+ "If enabled, pass the environment got by pyenv to jedi"
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-pyls-plugins-jedi-environment nil
+ "Specify the environment that jedi runs on where <environmeent>/bin/python
+should be the python executable. This option will be prioritized over
+`lsp-pyls-plugins-jedi-use-pyenv-environment'."
+ :type 'string
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-pyls-plugins-jedi-completion-fuzzy nil
+ "If enabled, uses fuzzy completion in jedi. Requires pyls >= 0.32.0
+Can hit performance, as well as lsp-mode implements its own fuzzy search on
+completion items."
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "7.0"))
+
+(defcustom lsp-pyls-plugins-jedi-completion-include-class-objects t
+ "If enabled, adds class objects to completion in order to avoid snippet
+with init args.
+
+Has no effect if `lsp-pyls-plugins-jedi-completion-include-params' is disabled.
+Requires pyls >= 0.33.0"
+ :type 'boolean
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "7.0"))
+
+(defcustom lsp-pyls-rename-backend 'jedi
+ "Choose renaming backend.
+
+Jedi is preferred but only works for python >= 3.6 and pyls >= 0.32.0
+Beware that Jedi is lazy and doesn't scan the whole project.
+So it will rename only references it can find."
+ :type '(choice (const :tag "jedi" jedi)
+ (const :tag "rope" rope))
+ :group 'lsp-pyls
+ :package-version '(lsp-mode . "7.0"))
+
+
+(defun lsp-pyls-get-pyenv-environment ()
+ "Get the pyenv-managed environment for current workspace, where
+<ENV>/bin/python is the corresponding Python executable"
+ (if lsp-pyls-plugins-jedi-environment
+ lsp-pyls-plugins-jedi-environment
+ (when lsp-pyls-plugins-jedi-use-pyenv-environment
+ (let ((pyenv-version (getenv "PYENV_VERSION"))
+ (root (lsp-seq-first (lsp-find-roots-for-workspace lsp--cur-workspace (lsp-session)))))
+ (when root
+ (setenv "PYENV_VERSION" nil)
+ (let* ((pyenv-command-path (executable-find "pyenv"))
+ (python-env (when pyenv-command-path
+ (f-parent
+ (f-parent
+ (shell-command-to-string
+ (format "PYENV_DIR='%s' %s which python"
+ root pyenv-command-path)))))))
+ (if python-env (lsp--info "Configure pyls with environment: %s" python-env)
+ (lsp--warn "Can't find the python environment for
+ %s even if
+ `lsp-pyls-plugins-jedi-use-pyenv-environment` is
+ enabled") root)
+ (setenv "PYENV_VERSION" pyenv-version)
+ python-env))))))
+
+(lsp-register-custom-settings
+ '(("pyls.rope.ropeFolder" lsp-pyls-rope-rope-folder)
+ ("pyls.rope.extensionModules" lsp-pyls-rope-extension-modules)
+ ("pyls.plugins.rope_rename.enabled" (lambda () (eq lsp-pyls-rename-backend 'rope)) t)
+ ("pyls.plugins.autopep8.enabled" lsp-pyls-plugins-autopep8-enabled t)
+ ("pyls.plugins.yapf.enabled" lsp-pyls-plugins-yapf-enabled t)
+ ("pyls.plugins.rope_completion.enabled" lsp-pyls-plugins-rope-completion-enabled t)
+ ("pyls.plugins.pyflakes.enabled" lsp-pyls-plugins-pyflakes-enabled t)
+ ("pyls.plugins.pydocstyle.matchDir" lsp-pyls-plugins-pydocstyle-match-dir)
+ ("pyls.plugins.pydocstyle.match" lsp-pyls-plugins-pydocstyle-match)
+ ("pyls.plugins.pydocstyle.select" lsp-pyls-plugins-pydocstyle-select)
+ ("pyls.plugins.pydocstyle.ignore" lsp-pyls-plugins-pydocstyle-ignore)
+ ("pyls.plugins.pydocstyle.addSelect" lsp-pyls-plugins-pydocstyle-add-select)
+ ("pyls.plugins.pydocstyle.addIgnore" lsp-pyls-plugins-pydocstyle-add-ignore)
+ ("pyls.plugins.pydocstyle.convention" lsp-pyls-plugins-pydocstyle-convention)
+ ("pyls.plugins.pydocstyle.enabled" lsp-pyls-plugins-pydocstyle-enabled t)
+ ("pyls.plugins.pycodestyle.maxLineLength" lsp-pyls-plugins-pycodestyle-max-line-length)
+ ("pyls.plugins.pycodestyle.hangClosing" lsp-pyls-plugins-pycodestyle-hang-closing t)
+ ("pyls.plugins.pycodestyle.ignore" lsp-pyls-plugins-pycodestyle-ignore)
+ ("pyls.plugins.pycodestyle.select" lsp-pyls-plugins-pycodestyle-select)
+ ("pyls.plugins.pycodestyle.filename" lsp-pyls-plugins-pycodestyle-filename)
+ ("pyls.plugins.pycodestyle.exclude" lsp-pyls-plugins-pycodestyle-exclude)
+ ("pyls.plugins.pycodestyle.enabled" lsp-pyls-plugins-pycodestyle-enabled t)
+ ("pyls.plugins.pylint.enabled" lsp-pyls-plugins-pylint-enabled t)
+ ("pyls.plugins.pylint.args" lsp-pyls-plugins-pylint-args)
+ ("pyls.plugins.flake8.enabled" lsp-pyls-plugins-flake8-enabled)
+ ("pyls.plugins.flake8.exclude" lsp-pyls-plugins-flake8-exclude)
+ ("pyls.plugins.flake8.filename" lsp-pyls-plugins-flake8-filename)
+ ("pyls.plugins.flake8.hangClosing" lsp-pyls-plugins-flake8-hang-closing)
+ ("pyls.plugins.flake8.ignore" lsp-pyls-plugins-flake8-ignore)
+ ("pyls.plugins.flake8.maxLineLength" lsp-pyls-plugins-flake8-max-line-length)
+ ("pyls.plugins.flake8.select" lsp-pyls-plugins-flake8-select)
+ ("pyls.plugins.flake8.config" lsp-pyls-plugins-flake8-config)
+ ("pyls.plugins.preload.modules" lsp-pyls-plugins-preload-modules)
+ ("pyls.plugins.preload.enabled" lsp-pyls-plugins-preload-enabled t)
+ ("pyls.plugins.mccabe.threshold" lsp-pyls-plugins-mccabe-threshold)
+ ("pyls.plugins.mccabe.enabled" lsp-pyls-plugins-mccabe-enabled t)
+ ("pyls.plugins.jedi_symbols.all_scopes" lsp-pyls-plugins-jedi-symbols-all-scopes t)
+ ("pyls.plugins.jedi_symbols.enabled" lsp-pyls-plugins-jedi-symbols-enabled t)
+ ("pyls.plugins.jedi_signature_help.enabled" lsp-pyls-plugins-jedi-signature-help-enabled t)
+ ("pyls.plugins.jedi_references.enabled" lsp-pyls-plugins-jedi-references-enabled t)
+ ("pyls.plugins.jedi_hover.enabled" lsp-pyls-plugins-jedi-hover-enabled t)
+ ("pyls.plugins.jedi_definition.follow_builtin_imports" lsp-pyls-plugins-jedi-definition-follow-builtin-imports t)
+ ("pyls.plugins.jedi_definition.follow_imports" lsp-pyls-plugins-jedi-definition-follow-imports t)
+ ("pyls.plugins.jedi_definition.enabled" lsp-pyls-plugins-jedi-definition-enabled t)
+ ("pyls.plugins.jedi_completion.include_params" lsp-pyls-plugins-jedi-completion-include-params t)
+ ("pyls.plugins.jedi_completion.enabled" lsp-pyls-plugins-jedi-completion-enabled t)
+ ("pyls.plugins.jedi_completion.include_class_objects" lsp-pyls-plugins-jedi-completion-include-class-objects t)
+ ("pyls.plugins.jedi.environment" lsp-pyls-get-pyenv-environment)
+ ("pyls.plugins.jedi_completion.fuzzy" lsp-pyls-plugins-jedi-completion-fuzzy t)
+ ("pyls.plugins.jedi_rename.enabled" (lambda () (eq lsp-pyls-rename-backend 'jedi)) t)
+ ("pyls.configurationSources" lsp-pyls-configuration-sources)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda () lsp-clients-python-command))
+ :major-modes '(python-mode cython-mode)
+ :priority -2
+ :server-id 'pyls
+ :library-folders-fn (lambda (_workspace) lsp-clients-python-library-directories)
+ :initialized-fn (lambda (workspace)
+ (unless lsp-pyls-disable-warning
+ (warn (concat "The palantir python-language-server (pyls) is unmaintained; "
+ "a maintained fork is the python-lsp-server (pylsp) project; "
+ "you can install it with pip via: pip install python-lsp-server")))
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "pyls"))))))
+
+(lsp-consistency-check lsp-pyls)
+
+(provide 'lsp-pyls)
+;;; lsp-pyls.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pylsp.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pylsp.el
new file mode 100644
index 0000000..a24862c
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-pylsp.el
@@ -0,0 +1,434 @@
+;;; lsp-pylsp.el --- python-lsp-server support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Doug Davis
+
+;; Author: Doug Davis <ddavis@ddavis.io>
+;; Keywords: language tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; pylsp configuration
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-pylsp nil
+ "LSP support for Python, using python-lsp's Python Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/python-lsp/python-lsp-server"))
+
+(defcustom lsp-clients-pylsp-library-directories '("/usr/")
+ "List of directories which will be considered to be libraries."
+ :risky t
+ :type '(repeat string)
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-server-command '("pylsp")
+ "Command to start pylsp."
+ :risky t
+ :group 'lsp-pylsp
+ :type '(repeat string))
+
+(defcustom lsp-pylsp-configuration-sources ["flake8"]
+ "List of configuration sources to use."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-completion-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-completion-include-params t
+ "Auto-completes methods and classes with tabstops for each
+parameter."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-definition-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-definition-follow-imports t
+ "The goto call will follow imports."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-definition-follow-builtin-imports t
+ "If follow_imports is True will decide if it follow builtin
+imports."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-hover-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-references-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-signature-help-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-symbols-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-symbols-all-scopes t
+ "If True lists the names of all scopes instead of only the
+module namespace."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-mccabe-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-mccabe-threshold 15
+ "The minimum threshold that triggers warnings about cyclomatic
+complexity."
+ :type 'number
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-preload-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-preload-modules nil
+ "List of modules to import on startup"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pylint-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pylint-args []
+ "Arguments, passed to pylint"
+ :risky t
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-exclude nil
+ "Exclude files or directories which match these patterns."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-filename nil
+ "When parsing directories, only check filenames matching these
+patterns."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-select nil
+ "Select errors and warnings"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-ignore nil
+ "Ignore errors and warnings"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-hang-closing nil
+ "Hang closing bracket instead of matching indentation of
+opening bracket's line."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pycodestyle-max-line-length nil
+ "Set maximum allowed line length."
+ :type 'number
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-convention nil
+ "Choose the basic list of checked errors by specifying an
+existing convention."
+ :type '(choice (:tag "pep257" "numpy"))
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-add-ignore nil
+ "Ignore errors and warnings in addition to the specified
+convention."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-add-select nil
+ "Select errors and warnings in addition to the specified
+convention."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-ignore nil
+ "Ignore errors and warnings"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-select nil
+ "Select errors and warnings"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-match "(?!test_).*\\.py"
+ "Check only files that exactly match the given regular
+expression; default is to match files that don't start with
+'test_' but end with '.py'."
+ :type 'string
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pydocstyle-match-dir "[^\\.].*"
+ "Search only dirs that exactly match the given regular
+expression; default is to match dirs which do not begin with a
+dot."
+ :type 'string
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-pyflakes-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-rope-completion-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-autopep8-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-yapf-enabled nil
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-rope-extension-modules nil
+ "Builtin and c-extension modules that are allowed to be
+imported and inspected by rope."
+ :type 'string
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-rope-rope-folder nil
+ "The name of the folder in which rope stores project
+configurations and data. Pass `nil` for not using such a folder
+at all."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-enabled t
+ "Enable or disable the plugin."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-exclude nil
+ "List of glob patterns to exclude from checks."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-filename nil
+ "List of glob patterns to include for checks."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-hang-closing nil
+ "Toggle whether pycodestyle should enforce matching the indentation of the
+opening bracket’s line. When you specify this, it will prefer that you hang the
+closing bracket rather than match the indentation."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-ignore nil
+ "A list of codes to ignore."
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-max-line-length nil
+ "Set the maximum length that any line (with some exceptions) may be.
+Exceptions include lines that are either strings or comments which are
+entirely URLs."
+ :type 'integer
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-select nil
+ "Specify the list of error codes you wish Flake8 to report. Similarly to
+`lsp-pylsp-plugins-flake8-ignore'. You can specify a portion of an error code to
+get all that start with that string. For example, you can use E, E4, E43, and
+E431"
+ :type 'lsp-string-vector
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-flake8-config nil
+ "A path to a config file that will be the only config file read and used.
+This will cause Flake8 to ignore all other config files that exist.
+
+NOTE: other parameters as `lsp-pylsp-plugins-flake8-max-line-length' take
+precedence over parameters referenced in config."
+ :type 'string
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-use-pyenv-environment nil
+ "If enabled, pass the environment got by pyenv to jedi"
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-environment nil
+ "Specify the environment that jedi runs on where <environmeent>/bin/python
+should be the python executable. This option will be prioritized over
+`lsp-pylsp-plugins-jedi-use-pyenv-environment'."
+ :type 'string
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-completion-fuzzy nil
+ "If enabled, uses fuzzy completion in jedi. Requires pylsp >= 0.32.0
+Can hit performance, as well as lsp-mode implements its own fuzzy search on
+completion items."
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-plugins-jedi-completion-include-class-objects t
+ "If enabled, adds class objects to completion in order to avoid snippet
+with init args.
+
+Has no effect if `lsp-pylsp-plugins-jedi-completion-include-params' is disabled.
+Requires pylsp >= 0.33.0"
+ :type 'boolean
+ :group 'lsp-pylsp)
+
+(defcustom lsp-pylsp-rename-backend 'jedi
+ "Choose renaming backend.
+
+Jedi is preferred but only works for python >= 3.6 and pylsp >= 0.32.0
+Beware that Jedi is lazy and doesn't scan the whole project.
+So it will rename only references it can find."
+ :type '(choice (const :tag "jedi" jedi)
+ (const :tag "rope" rope))
+ :group 'lsp-pylsp)
+
+(defun lsp-pylsp-get-pyenv-environment ()
+ "Get the pyenv-managed environment for current workspace, where
+<ENV>/bin/python is the corresponding Python executable"
+ (if lsp-pylsp-plugins-jedi-environment
+ lsp-pylsp-plugins-jedi-environment
+ (when lsp-pylsp-plugins-jedi-use-pyenv-environment
+ (let ((pyenv-version (getenv "PYENV_VERSION"))
+ (root (lsp-seq-first (lsp-find-roots-for-workspace lsp--cur-workspace (lsp-session)))))
+ (when root
+ (setenv "PYENV_VERSION" nil)
+ (let* ((pyenv-command-path (executable-find "pyenv"))
+ (python-env (when pyenv-command-path
+ (f-parent
+ (f-parent
+ (shell-command-to-string
+ (format "PYENV_DIR='%s' %s which python"
+ root pyenv-command-path)))))))
+ (if python-env (lsp--info "Configure pylsp with environment: %s" python-env)
+ (lsp--warn "Can't find the python environment for
+ %s even if
+ `lsp-pylsp-plugins-jedi-use-pyenv-environment` is
+ enabled") root)
+ (setenv "PYENV_VERSION" pyenv-version)
+ python-env))))))
+
+(lsp-register-custom-settings
+ '(("pylsp.rope.ropeFolder" lsp-pylsp-rope-rope-folder)
+ ("pylsp.rope.extensionModules" lsp-pylsp-rope-extension-modules)
+ ("pylsp.plugins.rope_rename.enabled" (lambda () (eq lsp-pylsp-rename-backend 'rope)) t)
+ ("pylsp.plugins.autopep8.enabled" lsp-pylsp-plugins-autopep8-enabled t)
+ ("pylsp.plugins.yapf.enabled" lsp-pylsp-plugins-yapf-enabled t)
+ ("pylsp.plugins.rope_completion.enabled" lsp-pylsp-plugins-rope-completion-enabled t)
+ ("pylsp.plugins.pyflakes.enabled" lsp-pylsp-plugins-pyflakes-enabled t)
+ ("pylsp.plugins.pydocstyle.matchDir" lsp-pylsp-plugins-pydocstyle-match-dir)
+ ("pylsp.plugins.pydocstyle.match" lsp-pylsp-plugins-pydocstyle-match)
+ ("pylsp.plugins.pydocstyle.select" lsp-pylsp-plugins-pydocstyle-select)
+ ("pylsp.plugins.pydocstyle.ignore" lsp-pylsp-plugins-pydocstyle-ignore)
+ ("pylsp.plugins.pydocstyle.addSelect" lsp-pylsp-plugins-pydocstyle-add-select)
+ ("pylsp.plugins.pydocstyle.addIgnore" lsp-pylsp-plugins-pydocstyle-add-ignore)
+ ("pylsp.plugins.pydocstyle.convention" lsp-pylsp-plugins-pydocstyle-convention)
+ ("pylsp.plugins.pydocstyle.enabled" lsp-pylsp-plugins-pydocstyle-enabled t)
+ ("pylsp.plugins.pycodestyle.maxLineLength" lsp-pylsp-plugins-pycodestyle-max-line-length)
+ ("pylsp.plugins.pycodestyle.hangClosing" lsp-pylsp-plugins-pycodestyle-hang-closing t)
+ ("pylsp.plugins.pycodestyle.ignore" lsp-pylsp-plugins-pycodestyle-ignore)
+ ("pylsp.plugins.pycodestyle.select" lsp-pylsp-plugins-pycodestyle-select)
+ ("pylsp.plugins.pycodestyle.filename" lsp-pylsp-plugins-pycodestyle-filename)
+ ("pylsp.plugins.pycodestyle.exclude" lsp-pylsp-plugins-pycodestyle-exclude)
+ ("pylsp.plugins.pycodestyle.enabled" lsp-pylsp-plugins-pycodestyle-enabled t)
+ ("pylsp.plugins.pylint.enabled" lsp-pylsp-plugins-pylint-enabled t)
+ ("pylsp.plugins.pylint.args" lsp-pylsp-plugins-pylint-args)
+ ("pylsp.plugins.flake8.enabled" lsp-pylsp-plugins-flake8-enabled)
+ ("pylsp.plugins.flake8.exclude" lsp-pylsp-plugins-flake8-exclude)
+ ("pylsp.plugins.flake8.filename" lsp-pylsp-plugins-flake8-filename)
+ ("pylsp.plugins.flake8.hangClosing" lsp-pylsp-plugins-flake8-hang-closing)
+ ("pylsp.plugins.flake8.ignore" lsp-pylsp-plugins-flake8-ignore)
+ ("pylsp.plugins.flake8.maxLineLength" lsp-pylsp-plugins-flake8-max-line-length)
+ ("pylsp.plugins.flake8.select" lsp-pylsp-plugins-flake8-select)
+ ("pylsp.plugins.flake8.config" lsp-pylsp-plugins-flake8-config)
+ ("pylsp.plugins.preload.modules" lsp-pylsp-plugins-preload-modules)
+ ("pylsp.plugins.preload.enabled" lsp-pylsp-plugins-preload-enabled t)
+ ("pylsp.plugins.mccabe.threshold" lsp-pylsp-plugins-mccabe-threshold)
+ ("pylsp.plugins.mccabe.enabled" lsp-pylsp-plugins-mccabe-enabled t)
+ ("pylsp.plugins.jedi_symbols.all_scopes" lsp-pylsp-plugins-jedi-symbols-all-scopes t)
+ ("pylsp.plugins.jedi_symbols.enabled" lsp-pylsp-plugins-jedi-symbols-enabled t)
+ ("pylsp.plugins.jedi_signature_help.enabled" lsp-pylsp-plugins-jedi-signature-help-enabled t)
+ ("pylsp.plugins.jedi_references.enabled" lsp-pylsp-plugins-jedi-references-enabled t)
+ ("pylsp.plugins.jedi_hover.enabled" lsp-pylsp-plugins-jedi-hover-enabled t)
+ ("pylsp.plugins.jedi_definition.follow_builtin_imports" lsp-pylsp-plugins-jedi-definition-follow-builtin-imports t)
+ ("pylsp.plugins.jedi_definition.follow_imports" lsp-pylsp-plugins-jedi-definition-follow-imports t)
+ ("pylsp.plugins.jedi_definition.enabled" lsp-pylsp-plugins-jedi-definition-enabled t)
+ ("pylsp.plugins.jedi_completion.include_params" lsp-pylsp-plugins-jedi-completion-include-params t)
+ ("pylsp.plugins.jedi_completion.enabled" lsp-pylsp-plugins-jedi-completion-enabled t)
+ ("pylsp.plugins.jedi_completion.include_class_objects" lsp-pylsp-plugins-jedi-completion-include-class-objects t)
+ ("pylsp.plugins.jedi.environment" lsp-pylsp-get-pyenv-environment)
+ ("pylsp.plugins.jedi_completion.fuzzy" lsp-pylsp-plugins-jedi-completion-fuzzy t)
+ ("pylsp.plugins.jedi_rename.enabled" (lambda () (eq lsp-pylsp-rename-backend 'jedi)) t)
+ ("pylsp.configurationSources" lsp-pylsp-configuration-sources)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda () lsp-pylsp-server-command))
+ :major-modes '(python-mode cython-mode)
+ :priority -1
+ :server-id 'pylsp
+ :library-folders-fn (lambda (_workspace) lsp-clients-pylsp-library-directories)
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "pylsp"))))))
+
+(lsp-consistency-check lsp-pylsp)
+
+(provide 'lsp-pylsp)
+;;; lsp-pylsp.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-r.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-r.el
new file mode 100644
index 0000000..da54bc3
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-r.el
@@ -0,0 +1,49 @@
+;;; lsp-r.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, r
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the R Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-r nil
+ "LSP support for R."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/REditorSupport/languageserver"))
+
+(defcustom lsp-clients-r-server-command '("R" "--slave" "-e" "languageserver::run()")
+ "Command to start the R language server."
+ :group 'lsp-r
+ :risky t
+ :type '(repeat string))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-r-server-command)
+ :major-modes '(ess-r-mode)
+ :server-id 'lsp-r))
+
+
+(lsp-consistency-check lsp-r)
+
+(provide 'lsp-r)
+;;; lsp-r.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-racket.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-racket.el
new file mode 100644
index 0000000..6ca7b5a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-racket.el
@@ -0,0 +1,77 @@
+;;; lsp-racket.el --- lsp-mode racket integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 lsp-mode maintainers
+
+;; Author: lsp-mode maintainers
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Client for the Racket language server.
+
+;;; Code:
+
+(require 'ht)
+(require 'lsp-mode)
+
+
+;; racket-langserver
+
+(defgroup lsp-racket-langserver nil
+ "LSP support for Racket, using racket-langserver"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/jeapostrophe/racket-langserver"))
+
+(defcustom lsp-racket-langserver-command '("racket" "--lib" "racket-langserver")
+ "Command to start the server."
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-racket-langserver-command))
+ :major-modes '(racket-mode)
+ :priority 1
+ :server-id 'racket-langserver))
+
+
+;; Theia
+
+(defgroup lsp-racket-language-server nil
+ "LSP support for Racket, using racket-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/theia-ide/racket-language-server"))
+
+(defcustom lsp-racket-language-server-path "racket-language-server"
+ "Executable path for the server."
+ :type 'string
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-racket-language-server-colorize-handler (&rest _args)
+ "Handler for the colorize notification."
+ ;; TODO:
+ nil)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-racket-language-server-path))
+ :major-modes '(racket-mode)
+ :priority -1
+ :notification-handlers (ht ("racket/colorize" #'lsp-racket-language-server-colorize-handler))
+ :server-id 'racket-language-server))
+
+(lsp-consistency-check lsp-racket)
+
+(provide 'lsp-racket)
+;;; lsp-racket.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rf.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rf.el
new file mode 100644
index 0000000..eee0a16
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rf.el
@@ -0,0 +1,147 @@
+;;; lsp-rf.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, rf, robot
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Robot Framework.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-rf nil
+ "Settings for Robot Framework Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/tomi/vscode-rf-language-server"))
+
+(defcustom lsp-rf-language-server-start-command '("~/.nvm/versions/node/v9.11.2/bin/node" "~/.vscode/extensions/tomiturtiainen.rf-intellisense-2.8.0/server/server.js")
+ "Path to the server.js file of the rf-intellisense server.
+Accepts a list of strings (path/to/interpreter path/to/server.js)"
+ :type 'list
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-include-paths []
+ "An array of files that should be included by the parser.
+Glob patterns as strings are accepted (eg. *.robot between double quotes)"
+ :type 'lsp-string-vector
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-exclude-paths []
+ "An array of files that should be ignored by the parser.
+Glob patterns as strings are accepted (eg. *bad.robot between double quotes)"
+ :type 'lsp-string-vector
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-dir "~/.vscode/extensions/tomiturtiainen.rf-intellisense-2.8.0/server/library-docs/"
+ "Libraries directory for libraries in `lsp-rf-language-server-libraries'"
+ :type 'string
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-libraries ["BuiltIn-3.1.1" "Collections-3.0.4"]
+ "Libraries whose keywords are suggested with `auto-complete'."
+ :type '(repeat string)
+ ;; :type 'lsp-string-vector
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-log-level "debug"
+ "What language server log messages are printed."
+ :type 'string
+ ;; :type '(choice (:tag "off" "errors" "info" "debug"))
+ :group 'lsp-rf)
+
+(defcustom lsp-rf-language-server-trace-server "verbose"
+ "Traces the communication between VSCode and the rfLanguageServer service."
+ :type 'string
+ ;; :type '(choice (:tag "off" "messages" "verbose"))
+ :group 'lsp-rf)
+
+(defun parse-rf-language-server-library-dirs (dirs)
+ (vconcat (mapcar
+ (lambda (x)
+ (concat
+ (expand-file-name
+ lsp-rf-language-server-dir)
+ x
+ ".json"))
+ dirs)))
+
+(defun expand-start-command ()
+ (mapcar 'expand-file-name lsp-rf-language-server-start-command))
+
+(defun parse-rf-language-server-globs-to-regex (vector)
+ "Convert a VECTOR of globs to a regex."
+ (--> (mapcan #'lsp-glob-to-regexps vector)
+ (s-join "\\|" it)
+ (concat "\\(?:" it "\\)")))
+
+(defun parse-rf-language-server-include-path-regex (vector)
+ "Creates regexp to select files from workspace directory."
+ (let ((globs (if (eq vector [])
+ ["*.robot" "*.resource"]
+ vector)))
+ (parse-rf-language-server-globs-to-regex globs)))
+
+(defun parse-rf-language-server-exclude-paths (seq)
+ "Creates regexp to select files from workspace directory."
+ (if (eq lsp-rf-language-server-exclude-paths [])
+ seq
+ (cl-delete-if (lambda (x) (string-match-p
+ (parse-rf-language-server-globs-to-regex
+ lsp-rf-language-server-exclude-paths)
+ x))
+ seq)))
+
+(lsp-register-custom-settings
+ '(
+ ("rfLanguageServer.trace.server" lsp-rf-language-server-trace-server)
+ ("rfLanguageServer.logLevel" lsp-rf-language-server-log-level)
+ ("rfLanguageServer.libraries" lsp-rf-language-server-libraries)
+ ("rfLanguageServer.excludePaths" lsp-rf-language-server-exclude-paths)
+ ("rfLanguageServer.includePaths" lsp-rf-language-server-include-paths)))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (expand-start-command))
+ :major-modes '(robot-mode)
+ :server-id 'rf-intellisense
+ ;; :library-folders-fn (lambda (_workspace)
+ ;; lsp-rf-language-server-libraries)
+ :library-folders-fn (lambda (_workspace)
+ (parse-rf-language-server-library-dirs
+ lsp-rf-language-server-libraries))
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "rfLanguageServer"))
+ (lsp-request "buildFromFiles"
+ (list :files
+ (vconcat
+ (parse-rf-language-server-exclude-paths
+ (directory-files-recursively
+ (lsp--workspace-root workspace)
+ (parse-rf-language-server-include-path-regex
+ lsp-rf-language-server-include-paths))))))))))
+
+
+
+(lsp-consistency-check lsp-rf)
+
+(provide 'lsp-rf)
+;;; lsp-rf.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rust.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rust.el
new file mode 100644
index 0000000..a85aba5
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-rust.el
@@ -0,0 +1,1100 @@
+;;; lsp-rust.el --- Rust Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-rust client
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'ht)
+(require 'dash)
+
+(defgroup lsp-rust nil
+ "LSP support for Rust, using Rust Language Server or rust-analyzer."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/rust-lang/rls")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-server 'rust-analyzer
+ "Choose LSP server."
+ :type '(choice (const :tag "rls" rls)
+ (const :tag "rust-analyzer" rust-analyzer))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2"))
+
+;; RLS
+
+(defcustom lsp-rust-rls-server-command '("rls")
+ "Command to start RLS."
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-library-directories '("~/.cargo/registry/src" "~/.rustup/toolchains")
+ "List of directories which will be considered to be libraries."
+ :risky t
+ :type '(repeat string)
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-sysroot nil
+ "If non-nil, use the given path as the sysroot for all rustc invocations
+instead of trying to detect the sysroot automatically."
+ :type '(choice
+ (const :tag "None" nil)
+ (string :tag "Sysroot"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-target nil
+ "If non-nil, use the given target triple for all rustc invocations."
+ :type '(choice
+ (const :tag "None" nil)
+ (string :tag "Target"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-rustflags nil
+ "Flags added to RUSTFLAGS."
+ :type '(choice
+ (const :tag "None" nil)
+ (string :tag "Flags"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-clear-env-rust-log t
+ "Clear the RUST_LOG environment variable before running rustc or cargo."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-build-lib nil
+ "If non-nil, checks the project as if you passed the `--lib' argument to
+cargo.
+
+Mutually exclusive with, and preferred over, `lsp-rust-build-bin'. (Unstable)"
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-build-bin nil
+ "If non-nil, checks the project as if you passed `-- bin <build_bin>'
+argument to cargo.
+
+Mutually exclusive with `lsp-rust-build-lib'. (Unstable)"
+ :type '(choice
+ (const :tag "None" nil)
+ (string :tag "Binary"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-cfg-test nil
+ "If non-nil, checks the project as if you were running `cargo test' rather
+than cargo build.
+
+I.e., compiles (but does not run) test code."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-unstable-features nil
+ "Enable unstable features."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-wait-to-build nil
+ "Time in milliseconds between receiving a change notification
+and starting build. If not specified, automatically inferred by
+the latest build duration."
+ :type '(choice
+ (const :tag "Auto" nil)
+ (number :tag "Time"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-show-warnings t
+ "Show warnings."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-crate-blacklist [
+ "cocoa"
+ "gleam"
+ "glium"
+ "idna"
+ "libc"
+ "openssl"
+ "rustc_serialize"
+ "serde"
+ "serde_json"
+ "typenum"
+ "unicode_normalization"
+ "unicode_segmentation"
+ "winapi"
+ ]
+ "A list of Cargo crates to blacklist."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-build-on-save nil
+ "Only index the project when a file is saved and not on change."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-features []
+ "List of Cargo features to enable."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-all-features nil
+ "Enable all Cargo features."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-analyzer-cargo-target nil
+ "Compilation target (target triple)."
+ :type 'string
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-no-default-features nil
+ "Do not enable default Cargo features."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-racer-completion t
+ "Enables code completion using racer."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-clippy-preference "opt-in"
+ "Controls eagerness of clippy diagnostics when available.
+Valid values are (case-insensitive):
+ - \"off\": Disable clippy lints.
+ - \"opt-in\": Clippy lints are shown when crates specify `#![warn(clippy)]'.
+ - \"on\": Clippy lints enabled for all crates in workspace.
+
+You need to install clippy via rustup if you haven't already."
+ :type '(choice
+ (const "on")
+ (const "opt-in")
+ (const "off"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-jobs nil
+ "Number of Cargo jobs to be run in parallel."
+ :type '(choice
+ (const :tag "Auto" nil)
+ (number :tag "Jobs"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-all-targets t
+ "Checks the project as if you were running cargo check --all-targets.
+I.e., check all targets and integration tests too."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-target-dir nil
+ "When specified, it places the generated analysis files at the
+specified target directory. By default it is placed target/rls
+directory."
+ :type '(choice
+ (const :tag "Default" nil)
+ (string :tag "Directory"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-rustfmt-path nil
+ "When specified, RLS will use the Rustfmt pointed at the path
+instead of the bundled one"
+ :type '(choice
+ (const :tag "Bundled" nil)
+ (string :tag "Path"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-build-command nil
+ "EXPERIMENTAL (requires `rust.unstable_features')
+If set, executes a given program responsible for rebuilding save-analysis to be
+loaded by the RLS. The program given should output a list of resulting .json
+files on stdout.
+
+Implies `rust.build_on_save': true."
+ :type '(choice
+ (const :tag "None" nil)
+ (string :tag "Command"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-full-docs nil
+ "Instructs cargo to enable full documentation extraction during
+save-analysis while building the crate."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-rust-show-hover-context t
+ "Show additional context in hover tooltips when available. This
+is often the type local variable declaration."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-register-custom-settings
+ '(("rust.show_hover_context" lsp-rust-show-hover-context t)
+ ("rust.full_docs" lsp-rust-full-docs t)
+ ("rust.build_command" lsp-rust-build-command)
+ ("rust.rustfmt_path" lsp-rust-rustfmt-path)
+ ("rust.target_dir" lsp-rust-target-dir)
+ ("rust.all_targets" lsp-rust-all-targets t)
+ ("rust.jobs" lsp-rust-jobs)
+ ("rust.clippy_preference" lsp-rust-clippy-preference)
+ ("rust.racer_completion" lsp-rust-racer-completion t)
+ ("rust.no_default_features" lsp-rust-no-default-features t)
+ ("rust.all_features" lsp-rust-all-features t)
+ ("rust.features" lsp-rust-features)
+ ("rust.build_on_save" lsp-rust-build-on-save t)
+ ("rust.crate_blacklist" lsp-rust-crate-blacklist)
+ ("rust.show_warnings" lsp-rust-show-warnings t)
+ ("rust.wait_to_build" lsp-rust-wait-to-build)
+ ("rust.unstable_features" lsp-rust-unstable-features t)
+ ("rust.cfg_test" lsp-rust-cfg-test t)
+ ("rust.build_bin" lsp-rust-build-bin)
+ ("rust.build_lib" lsp-rust-build-lib t)
+ ("rust.clear_env_rust_log" lsp-rust-clear-env-rust-log t)
+ ("rust.rustflags" lsp-rust-rustflags)
+ ("rust.target" lsp-rust-target)
+ ("rust.sysroot" lsp-rust-sysroot)))
+
+(defun lsp-clients--rust-window-progress (workspace params)
+ "Progress report handling.
+PARAMS progress report notification data."
+ (-let [(&v1:ProgressParams :done? :message? :title) params]
+ (if (or done? (s-blank-str? message?))
+ (lsp-workspace-status nil workspace)
+ (lsp-workspace-status (format "%s - %s" title (or message? "")) workspace))))
+
+(lsp-defun lsp-rust--rls-run ((&Command :arguments? params))
+ (-let* (((&rls:Cmd :env :binary :args :cwd) (lsp-seq-first params))
+ (default-directory (or cwd (lsp-workspace-root) default-directory) ))
+ (compile
+ (format "%s %s %s"
+ (s-join " " (ht-amap (format "%s=%s" key value) env))
+ binary
+ (s-join " " args)))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-rust-rls-server-command))
+ :major-modes '(rust-mode rustic-mode)
+ :priority (if (eq lsp-rust-server 'rls) 1 -1)
+ :initialization-options '((omitInitBuild . t)
+ (cmdRun . t))
+ :notification-handlers (ht ("window/progress" 'lsp-clients--rust-window-progress))
+ :action-handlers (ht ("rls.run" 'lsp-rust--rls-run))
+ :library-folders-fn (lambda (_workspace) lsp-rust-library-directories)
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "rust"))))
+ :server-id 'rls))
+
+
+;; rust-analyzer
+(defcustom lsp-rust-analyzer-server-command '("rust-analyzer")
+ "Command to start rust-analyzer."
+ :type '(repeat string)
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-rust-analyzer-server-display-inlay-hints nil
+ "Show inlay hints."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-rust-analyzer-max-inlay-hint-length nil
+ "Max inlay hint length."
+ :type 'integer
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-display-parameter-hints nil
+ "Whether to show function parameter name inlay hints at the call site."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-display-chaining-hints nil
+ "Whether to show inlay type hints for method chains."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-lru-capacity nil
+ "Number of syntax trees rust-analyzer keeps in memory."
+ :type 'integer
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-cargo-watch-enable t
+ "Enable Cargo watch."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-cargo-watch-command "check"
+ "Cargo watch command."
+ :type 'string
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-cargo-watch-args []
+ "Cargo watch args."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-cargo-override-command []
+ "Advanced option, fully override the command rust-analyzer uses for checking.
+The command should include `--message=format=json` or similar option."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-cargo-all-targets t
+ "Cargo watch all targets or not."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-use-client-watching t
+ "Use client watching"
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-exclude-globs []
+ "Exclude globs"
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-exclude-dirs []
+ "These directories will be ignored by rust-analyzer."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-macro-expansion-method 'lsp-rust-analyzer-macro-expansion-default
+ "Use a different function if you want formatted macro expansion results and
+syntax highlighting."
+ :type 'function
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.2.2"))
+
+(defcustom lsp-rust-analyzer-diagnostics-enable t
+ "Whether to show native rust-analyzer diagnostics."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-diagnostics-enable-experimental t
+ "Whether to show native rust-analyzer diagnostics that are still experimental
+\(might have more false positives than usual)."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-diagnostics-disabled []
+ "List of native rust-analyzer diagnostics to disable."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-diagnostics-warnings-as-hint []
+ "List of warnings that should be displayed with hint severity."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-diagnostics-warnings-as-info []
+ "List of warnings that should be displayed with info severity."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(define-obsolete-variable-alias
+ 'lsp-rust-analyzer-cargo-load-out-dirs-from-check
+ 'lsp-rust-analyzer-cargo-run-build-scripts
+ "7.1.0")
+
+(defcustom lsp-rust-analyzer-cargo-run-build-scripts t
+ "Whether to run build scripts (`build.rs`) for more precise code analysis."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-rustfmt-extra-args []
+ "Additional arguments to rustfmt."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-rustfmt-override-command []
+ "Advanced option, fully override the command rust-analyzer uses
+for formatting."
+ :type 'lsp-string-vector
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-completion-add-call-parenthesis t
+ "Whether to add parenthesis when completing functions."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-completion-add-call-argument-snippets t
+ "Whether to add argument snippets when completing functions."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-completion-postfix-enable t
+ "Whether to show postfix snippets like `dbg`, `if`, `not`, etc."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-call-info-full t
+ "Whether to show function name and docs in parameter hints."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-proc-macro-enable nil
+ "Enable Proc macro support.
+Implies `lsp-rust-analyzer-cargo-run-build-scripts'"
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "6.3.2"))
+
+(defcustom lsp-rust-analyzer-import-merge-behaviour "full"
+ "The strategy to use when inserting new imports or merging imports.
+Valid values are:
+ - \"none\": No merging
+ - \"full\": Merge all layers of the import trees
+ - \"last\": Only merge the last layer of the import trees"
+ :type '(choice
+ (const "none")
+ (const "full")
+ (const "last"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-import-prefix "plain"
+ "The path structure for newly inserted paths to use.
+Valid values are:
+ - \"plain\": Insert import paths relative to the current module, using up to
+one `super' prefix if the parent module contains the requested item.
+ - \"by_self\": Prefix all import paths with `self' if they don't begin with
+`self', `super', `crate' or a crate name.
+ - \"by_crate\": Force import paths to be absolute by always starting
+them with `crate' or the crate name they refer to."
+ :type '(choice
+ (const "plain")
+ (const "by_self")
+ (const "by_crate"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-import-granularity "crate"
+ "How imports should be grouped into use statements."
+ :type '(choice
+ (const "crate" :doc "Merge imports from the same crate into a single use statement. This kind of nesting is only supported in Rust versions later than 1.24.")
+ (const "module" :doc "Merge imports from the same module into a single use statement.")
+ (const "item" :doc "Don’t merge imports at all, creating one import per item.")
+ (const "preserve" :doc "Do not change the granularity of any imports. For auto-import this has the same effect as `\"item\"'"))
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-cargo-auto-reload t
+ "Automatically refresh project info via `cargo metadata' on `Cargo.toml' changes."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-use-rustc-wrapper-for-build-scripts t
+ "Use `RUSTC_WRAPPER=rust-analyzer' when running build scripts to avoid
+compiling unnecessary things."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-completion-auto-import-enable t
+ "Toggles the additional completions that automatically add imports when
+completed. `lsp-completion-enable-additional-text-edit' must be non-nil
+ for this feature to be fully enabled."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-completion-auto-self-enable t
+ "Toggles the additional completions that automatically show method calls
+and field accesses with self prefixed to them when inside a method."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-import-enforce-granularity nil
+ "Whether to enforce the import granularity setting for all files.
+ If set to nil rust-analyzer will try to keep import styles consistent per file."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-import-group t
+ "Group inserted imports by the following order:
+https://rust-analyzer.github.io/manual.html#auto-import.
+ Groups are separated by newlines."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-highlighting-strings t
+ "Use semantic tokens for strings."
+ :type 'boolean
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-rust-analyzer-rustc-source nil
+ "Path to the Cargo.toml of the rust compiler workspace."
+ :type 'string
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defun lsp-rust-analyzer--make-init-options ()
+ "Init options for rust-analyzer"
+ `(:diagnostics (:enable ,(lsp-json-bool lsp-rust-analyzer-diagnostics-enable)
+ :enableExperimental ,(lsp-json-bool lsp-rust-analyzer-diagnostics-enable-experimental)
+ :disabled ,lsp-rust-analyzer-diagnostics-disabled
+ :warningsAsHint ,lsp-rust-analyzer-diagnostics-warnings-as-hint
+ :warningsAsInfo ,lsp-rust-analyzer-diagnostics-warnings-as-info)
+ :assist (:importMergeBehaviour ,lsp-rust-analyzer-import-merge-behaviour
+ :importPrefix ,lsp-rust-analyzer-import-prefix
+ :importGranularity ,lsp-rust-analyzer-import-granularity
+ :importEnforceGranularity ,(lsp-json-bool lsp-rust-analyzer-import-enforce-granularity)
+ :importGroup ,(lsp-json-bool lsp-rust-analyzer-import-group))
+ :lruCapacity ,lsp-rust-analyzer-lru-capacity
+ :checkOnSave (:enable ,(lsp-json-bool lsp-rust-analyzer-cargo-watch-enable)
+ :command ,lsp-rust-analyzer-cargo-watch-command
+ :extraArgs ,lsp-rust-analyzer-cargo-watch-args
+ :allTargets ,(lsp-json-bool lsp-rust-analyzer-cargo-all-targets)
+ :overrideCommand ,lsp-rust-analyzer-cargo-override-command)
+ :files (:exclude ,lsp-rust-analyzer-exclude-globs
+ :watcher ,(lsp-json-bool (if lsp-rust-analyzer-use-client-watching
+ "client"
+ "notify"))
+ :excludeDirs ,lsp-rust-analyzer-exclude-dirs)
+ :cargo (:allFeatures ,(lsp-json-bool lsp-rust-all-features)
+ :noDefaultFeatures ,(lsp-json-bool lsp-rust-no-default-features)
+ :features ,lsp-rust-features
+ :target ,lsp-rust-analyzer-cargo-target
+ :runBuildScripts ,(lsp-json-bool lsp-rust-analyzer-cargo-run-build-scripts)
+ ; Obsolete, but used by old Rust-Analyzer versions
+ :loadOutDirsFromCheck ,(lsp-json-bool lsp-rust-analyzer-cargo-run-build-scripts)
+ :autoreload ,(lsp-json-bool lsp-rust-analyzer-cargo-auto-reload)
+ :useRustcWrapperForBuildScripts ,(lsp-json-bool lsp-rust-analyzer-use-rustc-wrapper-for-build-scripts))
+ :rustfmt (:extraArgs ,lsp-rust-analyzer-rustfmt-extra-args
+ :overrideCommand ,lsp-rust-analyzer-rustfmt-override-command)
+ :inlayHints (:typeHints ,(lsp-json-bool lsp-rust-analyzer-server-display-inlay-hints)
+ :chainingHints ,(lsp-json-bool lsp-rust-analyzer-display-chaining-hints)
+ :parameterHints ,(lsp-json-bool lsp-rust-analyzer-display-parameter-hints)
+ :maxLength ,lsp-rust-analyzer-max-inlay-hint-length)
+ :completion (:addCallParenthesis ,(lsp-json-bool lsp-rust-analyzer-completion-add-call-parenthesis)
+ :addCallArgumentSnippets ,(lsp-json-bool lsp-rust-analyzer-completion-add-call-argument-snippets)
+ :postfix (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-postfix-enable))
+ :autoimport (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-auto-import-enable))
+ :autoself (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-auto-self-enable)))
+ :callInfo (:full ,(lsp-json-bool lsp-rust-analyzer-call-info-full))
+ :procMacro (:enable ,(lsp-json-bool lsp-rust-analyzer-proc-macro-enable))
+ :rustcSource ,lsp-rust-analyzer-rustc-source
+ :highlighting (:strings ,(lsp-json-bool lsp-rust-analyzer-highlighting-strings))))
+
+(defconst lsp-rust-notification-handlers
+ '(("rust-analyzer/publishDecorations" . (lambda (_w _p)))))
+
+(defconst lsp-rust-action-handlers
+ '())
+
+(define-derived-mode lsp-rust-analyzer-syntax-tree-mode special-mode "Rust-Analyzer-Syntax-Tree"
+ "Mode for the rust-analyzer syntax tree buffer.")
+
+(defun lsp-rust-analyzer-syntax-tree ()
+ "Display syntax tree for current buffer."
+ (interactive)
+ (-let* ((root (lsp-workspace-root default-directory))
+ (params (lsp-make-rust-analyzer-syntax-tree-params
+ :text-document (lsp--text-document-identifier)
+ :range? (if (use-region-p)
+ (lsp--region-to-range (region-beginning) (region-end))
+ (lsp--region-to-range (point-min) (point-max)))))
+ (results (lsp-send-request (lsp-make-request
+ "rust-analyzer/syntaxTree"
+ params))))
+ (let ((buf (get-buffer-create (format "*rust-analyzer syntax tree %s*" root)))
+ (inhibit-read-only t))
+ (with-current-buffer buf
+ (lsp-rust-analyzer-syntax-tree-mode)
+ (erase-buffer)
+ (insert results)
+ (goto-char (point-min)))
+ (pop-to-buffer buf))))
+
+(define-derived-mode lsp-rust-analyzer-status-mode special-mode "Rust-Analyzer-Status"
+ "Mode for the rust-analyzer status buffer.")
+
+(defun lsp-rust-analyzer-status ()
+ "Displays status information for rust-analyzer."
+ (interactive)
+ (-let* ((root (lsp-workspace-root default-directory))
+ (params (lsp-make-rust-analyzer-analyzer-status-params
+ :text-document (lsp--text-document-identifier)))
+ (results (lsp-send-request (lsp-make-request
+ "rust-analyzer/analyzerStatus"
+ params))))
+ (let ((buf (get-buffer-create (format "*rust-analyzer status %s*" root)))
+ (inhibit-read-only t))
+ (with-current-buffer buf
+ (lsp-rust-analyzer-status-mode)
+ (erase-buffer)
+ (insert results)
+ (pop-to-buffer buf)))))
+
+(defun lsp-rust-analyzer-join-lines ()
+ "Join selected lines into one, smartly fixing up whitespace and trailing commas."
+ (interactive)
+ (let* ((params (lsp-make-rust-analyzer-join-lines-params
+ :text-document (lsp--text-document-identifier)
+ :ranges (vector (if (use-region-p)
+ (lsp--region-to-range (region-beginning) (region-end))
+ (lsp--region-to-range (point) (point))))))
+ (result (lsp-send-request (lsp-make-request "experimental/joinLines" params))))
+ (lsp--apply-text-edits result 'code-action)))
+
+(defun lsp-rust-analyzer-reload-workspace ()
+ "Reload workspace, picking up changes from Cargo.toml"
+ (interactive)
+ (lsp--cur-workspace-check)
+ (lsp-send-request (lsp-make-request "rust-analyzer/reloadWorkspace")))
+
+(defcustom lsp-rust-analyzer-download-url
+ (format "https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/%s"
+ (pcase system-type
+ ('gnu/linux "rust-analyzer-x86_64-unknown-linux-gnu.gz")
+ ('darwin "rust-analyzer-x86_64-apple-darwin.gz")
+ ('windows-nt "rust-analyzer-x86_64-pc-windows-msvc.gz")))
+ "Automatic download url for Rust Analyzer"
+ :type 'string
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-store-path (f-join lsp-server-install-dir
+ "rust"
+ (if (eq system-type 'windows-nt)
+ "rust-analyzer.exe"
+ "rust-analyzer"))
+ "The path to the file in which `rust-analyzer' will be stored."
+ :type 'file
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-dependency
+ 'rust-analyzer
+ `(:download :url lsp-rust-analyzer-download-url
+ :decompress :gzip
+ :store-path lsp-rust-analyzer-store-path
+ :set-executable? t)
+ '(:system "rust-analyzer"))
+
+(lsp-defun lsp-rust--analyzer-run-single ((&Command :arguments?))
+ (lsp-rust-analyzer-run (lsp-seq-first arguments?)))
+
+(lsp-defun lsp-rust--analyzer-show-references
+ ((&Command :title :arguments? [_uri _filepos references]))
+ (lsp-show-xrefs (lsp--locations-to-xref-items references) nil
+ (s-contains-p "reference" title)))
+
+(declare-function dap-debug "ext:dap-mode" (template) t)
+
+(lsp-defun lsp-rust--analyzer-debug-lens ((&Command :arguments? [args]))
+ (lsp-rust-analyzer-debug args))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find
+ (cl-first lsp-rust-analyzer-server-command))
+ (lsp-package-path 'rust-analyzer)
+ "rust-analyzer")
+ ,@(cl-rest lsp-rust-analyzer-server-command))))
+ :major-modes '(rust-mode rustic-mode)
+ :priority (if (eq lsp-rust-server 'rust-analyzer) 1 -1)
+ :initialization-options 'lsp-rust-analyzer--make-init-options
+ :notification-handlers (ht<-alist lsp-rust-notification-handlers)
+ :action-handlers (ht ("rust-analyzer.runSingle" #'lsp-rust--analyzer-run-single)
+ ("rust-analyzer.debugSingle" #'lsp-rust--analyzer-debug-lens)
+ ("rust-analyzer.showReferences" #'lsp-rust--analyzer-show-references))
+ :library-folders-fn (lambda (_workspace) lsp-rust-library-directories)
+ :after-open-fn (lambda ()
+ (when lsp-rust-analyzer-server-display-inlay-hints
+ (lsp-rust-analyzer-inlay-hints-mode)))
+ :ignore-messages nil
+ :server-id 'rust-analyzer
+ :custom-capabilities `((experimental . ((snippetTextEdit . ,(and lsp-enable-snippet (featurep 'yasnippet))))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'rust-analyzer callback error-callback))))
+
+(defun lsp-rust-switch-server (&optional lsp-server)
+ "Switch priorities of lsp servers, unless LSP-SERVER is already active."
+ (interactive)
+ (let ((current-server (if (> (lsp--client-priority (gethash 'rls lsp-clients)) 0)
+ 'rls
+ 'rust-analyzer)))
+ (unless (eq lsp-server current-server)
+ (dolist (server '(rls rust-analyzer))
+ (when (natnump (setf (lsp--client-priority (gethash server lsp-clients))
+ (* (lsp--client-priority (gethash server lsp-clients)) -1)))
+ (message (format "Switched to server %s." server)))))))
+
+;; inlay hints
+
+(defvar-local lsp-rust-analyzer-inlay-hints-timer nil)
+
+(defface lsp-rust-analyzer-inlay-face
+ '((t :inherit font-lock-comment-face))
+ "The face to use for the Rust Analyzer inlays."
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.0"))
+
+(defface lsp-rust-analyzer-inlay-type-face
+ '((t :inherit lsp-rust-analyzer-inlay-face))
+ "Face for inlay type hints (e.g. inferred variable types)."
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-type-space-format "%s"
+ "Format string for spacing around variable inlays
+\(not part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-type-format ": %s"
+ "Format string for variable inlays (part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defface lsp-rust-analyzer-inlay-param-face
+ '((t :inherit lsp-rust-analyzer-inlay-face))
+ "Face for inlay parameter hints (e.g. function parameter names at call-site)."
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-param-space-format "%s "
+ "Format string for spacing around parameter inlays
+\(not part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-param-format "%s:"
+ "Format string for parameter inlays (part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defface lsp-rust-analyzer-inlay-chain-face
+ '((t :inherit lsp-rust-analyzer-inlay-face))
+ "Face for inlay chaining hints (e.g. inferred chain intermediate types)."
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-chain-space-format "%s"
+ "Format string for spacing around chain inlays (not part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-rust-analyzer-inlay-chain-format ": %s"
+ "Format string for chain inlays (part of the inlay face)."
+ :type '(string :tag "String")
+ :group 'lsp-rust
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-rust-analyzer-update-inlay-hints (buffer)
+ (if (and (lsp-rust-analyzer-initialized?)
+ (eq buffer (current-buffer)))
+ (lsp-request-async
+ "rust-analyzer/inlayHints"
+ (lsp-make-rust-analyzer-inlay-hints-params
+ :text-document (lsp--text-document-identifier))
+ (lambda (res)
+ (remove-overlays (point-min) (point-max) 'lsp-rust-analyzer-inlay-hint t)
+ (dolist (hint res)
+ (-let* (((&rust-analyzer:InlayHint :range :label :kind) hint)
+ ((&RangeToPoint :start :end) range)
+ (overlay (make-overlay start end nil 'front-advance 'end-advance)))
+ (overlay-put overlay 'lsp-rust-analyzer-inlay-hint t)
+ (overlay-put overlay 'evaporate t)
+ (cond
+ ((equal kind lsp/rust-analyzer-inlay-hint-kind-type-hint)
+ (overlay-put overlay 'after-string
+ (format lsp-rust-analyzer-inlay-type-space-format
+ (propertize (format lsp-rust-analyzer-inlay-type-format label)
+ 'font-lock-face 'lsp-rust-analyzer-inlay-type-face))))
+
+ ((equal kind lsp/rust-analyzer-inlay-hint-kind-param-hint)
+ (overlay-put overlay 'before-string
+ (format lsp-rust-analyzer-inlay-param-space-format
+ (propertize (format lsp-rust-analyzer-inlay-param-format label)
+ 'font-lock-face 'lsp-rust-analyzer-inlay-param-face))))
+
+ ((equal kind lsp/rust-analyzer-inlay-hint-kind-chaining-hint)
+ (overlay-put overlay 'after-string
+ (format lsp-rust-analyzer-inlay-chain-space-format
+ (propertize (format lsp-rust-analyzer-inlay-chain-format label)
+ 'font-lock-face 'lsp-rust-analyzer-inlay-chain-face))))))))
+ :mode 'tick))
+ nil)
+
+(defun lsp-rust-analyzer-initialized? ()
+ (when-let ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name))))
+ (eq 'initialized (lsp--workspace-status workspace))))
+
+(defun lsp-rust-analyzer-inlay-hints-change-handler (&rest _rest)
+ (when lsp-rust-analyzer-inlay-hints-timer
+ (cancel-timer lsp-rust-analyzer-inlay-hints-timer))
+ (setq lsp-rust-analyzer-inlay-hints-timer
+ (run-with-idle-timer 0.1 nil #'lsp-rust-analyzer-update-inlay-hints (current-buffer))))
+
+(define-minor-mode lsp-rust-analyzer-inlay-hints-mode
+ "Mode for displaying inlay hints."
+ :lighter nil
+ (cond
+ (lsp-rust-analyzer-inlay-hints-mode
+ (lsp-rust-analyzer-update-inlay-hints (current-buffer))
+ (add-hook 'lsp-on-change-hook #'lsp-rust-analyzer-inlay-hints-change-handler nil t))
+ (t
+ (remove-overlays (point-min) (point-max) 'lsp-rust-analyzer-inlay-hint t)
+ (remove-hook 'lsp-on-change-hook #'lsp-rust-analyzer-inlay-hints-change-handler t))))
+
+(defun lsp-rust-analyzer-expand-macro ()
+ "Expands the macro call at point recursively."
+ (interactive)
+ (-if-let* ((params (lsp-make-rust-analyzer-expand-macro-params
+ :text-document (lsp--text-document-identifier)
+ :position (lsp--cur-position)))
+ (response (lsp-send-request (lsp-make-request
+ "rust-analyzer/expandMacro"
+ params)))
+ ((&rust-analyzer:ExpandedMacro :expansion) response))
+ (funcall lsp-rust-analyzer-macro-expansion-method expansion)
+ (message "No macro found at point, or it could not be expanded.")))
+
+(defun lsp-rust-analyzer-macro-expansion-default (result)
+ "Default method for displaying macro expansion."
+ (let* ((root (lsp-workspace-root default-directory))
+ (buf (get-buffer-create (get-buffer-create (format "*rust-analyzer macro expansion %s*" root)))))
+ (with-current-buffer buf
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert result)
+ (special-mode)))
+ (display-buffer buf)))
+
+;; runnables
+(defvar lsp-rust-analyzer--last-runnable nil)
+
+(defun lsp-rust-analyzer--runnables ()
+ (lsp-send-request (lsp-make-request
+ "experimental/runnables"
+ (lsp-make-rust-analyzer-runnables-params
+ :text-document (lsp--text-document-identifier)
+ :position? (lsp--cur-position)))))
+
+(defun lsp-rust-analyzer--select-runnable ()
+ (lsp--completing-read
+ "Select runnable:"
+ (if lsp-rust-analyzer--last-runnable
+ (cons lsp-rust-analyzer--last-runnable
+ (-remove (-lambda ((&rust-analyzer:Runnable :label))
+ (equal label (lsp-get lsp-rust-analyzer--last-runnable :label)))
+ (lsp-rust-analyzer--runnables)))
+ (lsp-rust-analyzer--runnables))
+ (-lambda ((&rust-analyzer:Runnable :label)) label)))
+
+
+(defun lsp-rust-analyzer--common-runner (runnable)
+ "Execute a given RUNNABLE.
+
+Extract the arguments, prepare the minor mode (cargo-process-mode if possible)
+and run a compilation"
+ (-let* (((&rust-analyzer:Runnable :kind :label :args) runnable)
+ ((&rust-analyzer:RunnableArgs :cargo-args :executable-args :workspace-root?) args)
+ (default-directory (or workspace-root? default-directory)))
+ (if (not (string-equal kind "cargo"))
+ (lsp--error "'%s' runnable is not supported" kind)
+ (compilation-start
+ (string-join (append (list "cargo") cargo-args (when executable-args '("--")) executable-args '()) " ")
+ ;; cargo-process-mode is nice, but try to work without it...
+ (if (functionp 'cargo-process-mode) 'cargo-process-mode nil)
+ (lambda (_) (concat "*" label "*"))))))
+
+
+(defun lsp-rust-analyzer-run (runnable)
+ "Select and run a RUNNABLE action."
+ (interactive (list (lsp-rust-analyzer--select-runnable)))
+ (when (lsp-rust-analyzer--common-runner runnable)
+ (setq lsp-rust-analyzer--last-runnable runnable)))
+
+(defun lsp-rust-analyzer-debug (runnable)
+ "Select and debug a RUNNABLE action."
+ (interactive (list (lsp-rust-analyzer--select-runnable)))
+ (unless (featurep 'dap-cpptools)
+ (user-error "You must require `dap-cpptools'"))
+ (-let (((&rust-analyzer:Runnable
+ :args (&rust-analyzer:RunnableArgs :cargo-args :workspace-root? :executable-args)
+ :label) runnable))
+ (cl-case (aref cargo-args 0)
+ ("run" (aset cargo-args 0 "build"))
+ ("test" (when (-contains? (append cargo-args ()) "--no-run")
+ (cl-callf append cargo-args (list "--no-run")))))
+ (->> (append (list (executable-find "cargo"))
+ cargo-args
+ (list "--message-format=json"))
+ (s-join " ")
+ (shell-command-to-string)
+ (s-lines)
+ (-keep (lambda (s)
+ (condition-case nil
+ (-let* ((json-object-type 'plist)
+ ((msg &as &plist :reason :executable) (json-read-from-string s)))
+ (when (and executable (string= "compiler-artifact" reason))
+ executable))
+ (error))))
+ (funcall
+ (lambda (artifact-spec)
+ (pcase artifact-spec
+ (`() (user-error "No compilation artifacts or obtaining the runnable artifacts failed"))
+ (`(,spec) spec)
+ (_ (user-error "Multiple compilation artifacts are not supported")))))
+ (list :type "cppdbg"
+ :request "launch"
+ :name label
+ :args executable-args
+ :cwd workspace-root?
+ :sourceLanguages ["rust"]
+ :program)
+ (dap-debug))))
+
+(defun lsp-rust-analyzer-rerun (&optional runnable)
+ (interactive (list (or lsp-rust-analyzer--last-runnable
+ (lsp-rust-analyzer--select-runnable))))
+ (lsp-rust-analyzer-run (or runnable lsp-rust-analyzer--last-runnable)))
+
+;; goto parent module
+(cl-defun lsp-rust-find-parent-module (&key display-action)
+ "Find parent module of current module."
+ (interactive)
+ (lsp-find-locations "experimental/parentModule" nil :display-action display-action))
+
+(defun lsp-rust-analyzer-open-cargo-toml (&optional new-window)
+ "Open the closest Cargo.toml from the current file.
+
+Rust-Analyzer LSP protocol documented here and added in November 2020
+https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#open-cargotoml
+
+If NEW-WINDOW (interactively the prefix argument) is non-nil,
+open in a new window."
+ (interactive "P")
+ (-if-let (workspace (lsp-find-workspace 'rust-analyzer))
+ (-if-let* ((response (with-lsp-workspace workspace
+ (lsp-send-request (lsp-make-request
+ "experimental/openCargoToml"
+ (lsp-make-rust-analyzer-open-cargo-toml-params
+ :text-document (lsp--text-document-identifier))))))
+ ((&Location :uri :range) response))
+ (funcall (if new-window #'find-file-other-window #'find-file)
+ (lsp--uri-to-path uri))
+ (lsp--warn "Couldn't find a Cargo.toml file or your version of rust-analyzer doesn't support this extension"))
+ (lsp--error "OpenCargoToml is an extension available only with rust-analyzer")))
+
+
+(defun lsp-rust-analyzer--related-tests ()
+ "Get runnable test items related to the current TextDocumentPosition.
+Calls a rust-analyzer LSP extension endpoint that returns a wrapper over Runnable[]"
+ (lsp-send-request (lsp-make-request
+ "rust-analyzer/relatedTests"
+ (lsp--text-document-position-params))))
+
+(defun lsp-rust-analyzer--select-related-test ()
+ "Call the endpoint and ask for user selection.
+
+Cannot reuse `lsp-rust-analyzer--select-runnable' because the runnables endpoint
+responds with Runnable[], while relatedTests responds with TestInfo[], which is a wrapper
+over runnable. Also, this method doesn't set the `lsp-rust-analyzer--last-runnable' variable"
+ (-if-let* ((resp (lsp-rust-analyzer--related-tests))
+ (runnables (seq-map
+ #'lsp:rust-analyzer-related-tests-runnable
+ resp)))
+ (lsp--completing-read
+ "Select test: "
+ runnables
+ #'lsp:rust-analyzer-runnable-label)))
+
+(defun lsp-rust-analyzer-related-tests (runnable)
+ "Execute a RUNNABLE test related to the current document position.
+
+Rust-Analyzer LSP protocol extension
+https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#related-tests"
+ (interactive (list (lsp-rust-analyzer--select-related-test)))
+ (if runnable
+ (lsp-rust-analyzer--common-runner runnable)
+ (lsp--info "There are no tests related to the symbol at point")))
+
+
+(lsp-consistency-check lsp-rust)
+
+(provide 'lsp-rust)
+;;; lsp-rust.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-semantic-tokens.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-semantic-tokens.el
new file mode 100644
index 0000000..00e6b45
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-semantic-tokens.el
@@ -0,0 +1,758 @@
+;;; lsp-semantic-tokens.el --- Semantic tokens -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 emacs-lsp maintainers
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; Semantic tokens
+;; https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
+;;
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-semantic-tokens nil
+ "LSP support for semantic-tokens."
+ :prefix "lsp-semantic-tokens-"
+ :group 'lsp-mode
+ :tag "LSP Semantic tokens")
+
+(define-obsolete-variable-alias 'lsp-semantic-highlighting-warn-on-missing-face 'lsp-semantic-tokens-warn-on-missing-face "lsp-mode 7.1")
+
+(defcustom lsp-semantic-tokens-warn-on-missing-face nil
+ "Warning on missing face for token type/modifier.
+When non-nil, this option will emit a warning any time a token
+or modifier type returned by a language server has no face associated with it."
+ :group 'lsp-semantic-tokens
+ :type 'boolean)
+
+(defcustom lsp-semantic-tokens-apply-modifiers nil
+ "Whether semantic tokens should take token modifiers into account."
+ :group 'lsp-semantic-tokens
+ :type 'boolean)
+
+(defcustom lsp-semantic-tokens-allow-ranged-requests t
+ "Whether to use ranged semantic token requests when available.
+
+Note that even when this is set to t, delta requests will
+be preferred whenever possible, unless
+`lsp-semantic-tokens-allow-delta-requests' is false."
+ :group 'lsp-semantic-tokens
+ :type 'boolean)
+
+(defcustom lsp-semantic-tokens-allow-delta-requests t
+ "Whether to use semantic token delta requests when available.
+
+When supported by the language server, delta requests are always
+preferred over both full and ranged token requests."
+ :group 'lsp-semantic-tokens
+ :type 'boolean)
+
+(defface lsp-face-semhl-constant
+ '((t :inherit font-lock-constant-face))
+ "Face used for semantic highlighting scopes matching constant scopes."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-variable
+ '((t :inherit font-lock-variable-name-face))
+ "Face used for semantic highlighting scopes matching variable.*.
+Unless overridden by a more specific face association."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-function
+ '((t :inherit font-lock-function-name-face))
+ "Face used for semantic highlighting scopes matching entity.name.function.*.
+Unless overridden by a more specific face association."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-method
+ '((t :inherit lsp-face-semhl-function))
+ "Face used for semantic highlighting scopes matching entity.name.method.*.
+Unless overridden by a more specific face association."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-namespace
+ '((t :inherit font-lock-type-face :weight bold))
+ "Face used for semantic highlighting scopes matching entity.name.namespace.*.
+Unless overridden by a more specific face association."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-comment
+ '((t (:inherit font-lock-comment-face)))
+ "Face used for comments."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-keyword
+ '((t (:inherit font-lock-keyword-face)))
+ "Face used for keywords."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-string
+ '((t (:inherit font-lock-string-face)))
+ "Face used for keywords."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-number
+ '((t (:inherit font-lock-constant-face)))
+ "Face used for numbers."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-regexp
+ '((t (:inherit font-lock-string-face :slant italic)))
+ "Face used for regexps."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-operator
+ '((t (:inherit font-lock-function-name-face)))
+ "Face used for operators."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-namespace
+ '((t (:inherit font-lock-keyword-face)))
+ "Face used for namespaces."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-type
+ '((t (:inherit font-lock-type-face)))
+ "Face used for types."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-struct
+ '((t (:inherit font-lock-type-face)))
+ "Face used for structs."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-class
+ '((t (:inherit font-lock-type-face)))
+ "Face used for classes."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-interface
+ '((t (:inherit font-lock-type-face)))
+ "Face used for interfaces."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-enum
+ '((t (:inherit font-lock-type-face)))
+ "Face used for enums."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-type-parameter
+ '((t (:inherit font-lock-type-face)))
+ "Face used for type parameters."
+ :group 'lsp-semantic-tokens)
+
+;; function face already defined, move here when support
+;; for theia highlighting gets removed
+(defface lsp-face-semhl-member
+ '((t (:inherit font-lock-variable-name-face)))
+ "Face used for members."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-property
+ '((t (:inherit font-lock-variable-name-face)))
+ "Face used for properties."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-event
+ '((t (:inherit font-lock-variable-name-face)))
+ "Face used for event properties."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-macro
+ '((t (:inherit font-lock-preprocessor-face)))
+ "Face used for macros."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-variable
+ '((t (:inherit font-lock-variable-name-face)))
+ "Face used for variables."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-parameter
+ '((t (:inherit font-lock-variable-name-face)))
+ "Face used for parameters."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-label
+ '((t (:inherit font-lock-comment-face)))
+ "Face used for labels."
+ :group 'lsp-semantic-tokens)
+
+(defface lsp-face-semhl-deprecated
+ '((t :strike-through t))
+ "Face used for semantic highlighting scopes matching constant scopes."
+ :group 'lsp-semantic-tokens)
+
+(defvar lsp-semantic-token-faces
+ '(("comment" . lsp-face-semhl-comment)
+ ("keyword" . lsp-face-semhl-keyword)
+ ("string" . lsp-face-semhl-string)
+ ("number" . lsp-face-semhl-number)
+ ("regexp" . lsp-face-semhl-regexp)
+ ("operator" . lsp-face-semhl-operator)
+ ("namespace" . lsp-face-semhl-namespace)
+ ("type" . lsp-face-semhl-type)
+ ("struct" . lsp-face-semhl-struct)
+ ("class" . lsp-face-semhl-class)
+ ("interface" . lsp-face-semhl-interface)
+ ("enum" . lsp-face-semhl-enum)
+ ("typeParameter" . lsp-face-semhl-type-parameter)
+ ("function" . lsp-face-semhl-function)
+ ("method" . lsp-face-semhl-method)
+ ("member" . lsp-face-semhl-member)
+ ("property" . lsp-face-semhl-property)
+ ("event" . lsp-face-semhl-event)
+ ("macro" . lsp-face-semhl-macro)
+ ("variable" . lsp-face-semhl-variable)
+ ("parameter" . lsp-face-semhl-parameter)
+ ("label" . lsp-face-semhl-label)
+ ("enumConstant" . lsp-face-semhl-constant)
+ ("enumMember" . lsp-face-semhl-constant)
+ ("dependent" . lsp-face-semhl-type)
+ ("concept" . lsp-face-semhl-interface))
+ "Faces to use for semantic tokens.")
+
+(defvar lsp-semantic-token-modifier-faces
+ ;; TODO: add default definitions
+ '(("declaration" . lsp-face-semhl-interface)
+ ("deprecated" . lsp-face-semhl-deprecated)
+ ("readonly" . lsp-face-semhl-constant))
+ "Semantic tokens modifier faces.
+Faces to use for semantic token modifiers if
+`lsp-semantic-tokens-apply-modifiers' is non-nil.")
+
+(defvar lsp-semantic-tokens-capabilities
+ `((semanticTokens
+ . ((dynamicRegistration . t)
+ (requests . ((range . t) (full . t)))
+ (tokenModifiers . ,(if lsp-semantic-tokens-apply-modifiers
+ (apply 'vector (mapcar #'car lsp-semantic-token-modifier-faces)) []))
+ (tokenTypes . ,(apply 'vector (mapcar #'car lsp-semantic-token-faces)))
+ (formats . ["relative"])))))
+
+
+(defvar lsp--semantic-tokens-idle-timer nil)
+
+(defvar-local lsp--semantic-tokens-cache nil
+ "Previously returned token set.
+
+When non-nil, `lsp--semantic-tokens-cache' should adhere to the
+following lsp-interface:
+`(_SemanticTokensCache
+ (:_documentVersion :_ranged)
+ (:response :_region))'.")
+
+(defsubst lsp--semantic-tokens-putcache (k v)
+ "Set key K of `lsp--semantic-tokens-cache' to V."
+ (setq lsp--semantic-tokens-cache
+ (plist-put lsp--semantic-tokens-cache k v)))
+
+(defvar-local lsp--semantic-tokens-teardown nil)
+
+(defun lsp--semantic-tokens-request-full-token-set-when-idle (fontify-immediately)
+ "Request full token set after an idle timeout of `lsp-idle-delay'.
+
+If FONTIFY-IMMEDIATELY is non-nil, fontification will be performed immediately
+ once the corresponding response is received."
+ (when lsp--semantic-tokens-idle-timer (cancel-timer lsp--semantic-tokens-idle-timer))
+ (let ((buf (current-buffer)))
+ (setq lsp--semantic-tokens-idle-timer
+ (run-with-idle-timer
+ lsp-idle-delay
+ nil
+ (lambda ()
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (lsp--semantic-tokens-request nil fontify-immediately))))))))
+
+(defun lsp--semantic-tokens-ingest-range-response (response)
+ "Handle RESPONSE to semanticTokens/range request."
+ (lsp--semantic-tokens-putcache :response response)
+ (lsp--semantic-tokens-putcache :_ranged t)
+ (lsp--semantic-tokens-request-full-token-set-when-idle nil))
+
+(defun lsp--semantic-tokens-ingest-full-response (response)
+ "Handle RESPONSE to semanticTokens/full request."
+ (lsp--semantic-tokens-putcache :response response)
+ (lsp--semantic-tokens-putcache :_ranged nil))
+
+(defsubst lsp--semantic-tokens-apply-delta-edits (old-data edits)
+ "Apply EDITS obtained from full/delta request to OLD-DATA."
+ (let* ((old-token-count (length old-data))
+ (old-token-index 0)
+ (substrings))
+ (cl-loop
+ for edit across edits
+ when (< old-token-index (lsp-get edit :start))
+ do
+ (push (substring old-data old-token-index (lsp-get edit :start)) substrings)
+ (push (lsp-get edit :data) substrings)
+ (setq old-token-index (+ (lsp-get edit :start) (lsp-get edit :deleteCount)))
+ finally do (push (substring old-data old-token-index old-token-count) substrings))
+ (apply #'vconcat (nreverse substrings))))
+
+(defun lsp--semantic-tokens-ingest-full/delta-response (response)
+ "Handle RESPONSE to semanticTokens/full/delta request."
+ (if (lsp-get response :edits)
+ (let ((old-data (--> lsp--semantic-tokens-cache (plist-get it :response) (lsp-get it :data))))
+ (when old-data
+ (lsp--semantic-tokens-putcache
+ :response (lsp-put response
+ :data (lsp--semantic-tokens-apply-delta-edits
+ old-data (lsp-get response :edits))))
+ (lsp--semantic-tokens-putcache :_ranged nil)))
+ ;; server decided to send full response instead
+ (lsp--semantic-tokens-ingest-full-response response)))
+
+
+(defun lsp--semantic-tokens-request (region fontify-immediately)
+ "Send semantic tokens request to the language server.
+
+A full/delta request will be sent if delta requests are supported by
+the language server, allowed via `lsp-semantic-tokens-allow-delta-requests',
+and if a full set of tokens had previously been received.
+Otherwise, a ranged request will be dispatched if REGION is non-nil,
+ranged requests are supported by the language server, and allowed via
+`lsp-semantic-tokens-allow-delta-requests'. In all other cases, a full
+tokens request will be dispatched.
+
+If FONTIFY-IMMEDIATELY is non-nil, fontification will be performed immediately
+ upon receiving the response."
+ (let ((request-type "textDocument/semanticTokens/full")
+ (request `(:textDocument ,(lsp--text-document-identifier)))
+ (response-handler nil))
+ (cond
+ ((and lsp-semantic-tokens-allow-delta-requests
+ (lsp-feature? "textDocument/semanticTokensFull/Delta")
+ (--> lsp--semantic-tokens-cache
+ (plist-get it :response)
+ (and (lsp-get it :resultId) (lsp-get it :data) (not (lsp-get it :_ranged)))))
+ (setq request-type "textDocument/semanticTokens/full/delta")
+ (setq response-handler #'lsp--semantic-tokens-ingest-full/delta-response)
+ (setq request
+ (plist-put request :previousResultId
+ (lsp-get (plist-get lsp--semantic-tokens-cache :response) :resultId))))
+ ((and lsp-semantic-tokens-allow-ranged-requests region
+ (lsp-feature? "textDocument/semanticTokensRangeProvider"))
+ (setq request-type "textDocument/semanticTokens/range")
+ (setq request
+ (plist-put request :range (lsp--region-to-range (car region) (cdr region))))
+ (setq response-handler #'lsp--semantic-tokens-ingest-range-response))
+ (t (setq response-handler #'lsp--semantic-tokens-ingest-full-response)))
+ (when lsp--semantic-tokens-idle-timer (cancel-timer lsp--semantic-tokens-idle-timer))
+ (lsp-request-async
+ request-type request
+ (lambda (response)
+ (lsp--semantic-tokens-putcache :_documentVersion lsp--cur-version)
+ (funcall response-handler response)
+ (when fontify-immediately (font-lock-flush)))
+ :error-handler (lambda (&rest _) (lsp--semantic-tokens-request-full-token-set-when-idle t))
+ :mode 'tick
+ :cancel-token (format "semantic-tokens-%s" (lsp--buffer-uri)))))
+
+
+(defun lsp-semantic-tokens--fontify (old-fontify-region beg-orig end-orig &optional loudly)
+ "Apply fonts to retrieved semantic tokens.
+OLD-FONTIFY-REGION is the underlying region fontification function,
+e.g., `font-lock-fontify-region'.
+BEG-ORIG and END-ORIG deliminate the requested fontification region and maybe
+modified by OLD-FONTIFY-REGION.
+LOUDLY will be forwarded to OLD-FONTIFY-REGION as-is."
+ ;; TODO: support multiple language servers per buffer?
+ (let ((faces (seq-some #'lsp--workspace-semantic-tokens-faces lsp--buffer-workspaces))
+ (modifier-faces
+ (when lsp-semantic-tokens-apply-modifiers
+ (seq-some #'lsp--workspace-semantic-tokens-modifier-faces lsp--buffer-workspaces)))
+ old-bounds
+ beg end)
+ (cond
+ ((or (eq nil faces)
+ (eq nil lsp--semantic-tokens-cache)
+ (eq nil (plist-get lsp--semantic-tokens-cache :response)))
+ ;; default to non-semantic highlighting until first response has arrived
+ (funcall old-fontify-region beg-orig end-orig loudly))
+ ((not (= lsp--cur-version (plist-get lsp--semantic-tokens-cache :_documentVersion)))
+ ;; delay fontification until we have fresh tokens
+ '(jit-lock-bounds 0 . 0))
+ (t
+ (setq old-bounds (funcall old-fontify-region beg-orig end-orig loudly))
+ ;; this is to prevent flickering when semantic token highlighting
+ ;; is layered on top of, e.g., tree-sitter-hl, or clojure-mode's syntax highlighting.
+ (setq beg (min beg-orig (cadr old-bounds))
+ end (max end-orig (cddr old-bounds)))
+ (-let* ((inhibit-field-text-motion t)
+ (data (lsp-get (plist-get lsp--semantic-tokens-cache :response) :data))
+ (i0 0)
+ (i-max (1- (length data)))
+ (current-line 1)
+ (line-delta)
+ (column 0)
+ (face)
+ (line-start-pos)
+ (line-min)
+ (line-max-inclusive)
+ (text-property-beg)
+ (text-property-end))
+ (save-mark-and-excursion
+ (save-restriction
+ (widen)
+ (goto-char beg)
+ (goto-char (line-beginning-position))
+ (setq line-min (line-number-at-pos))
+ (with-silent-modifications
+ (goto-char end)
+ (goto-char (line-end-position))
+ (setq line-max-inclusive (line-number-at-pos))
+ (forward-line (- line-min line-max-inclusive))
+ (let ((skip-lines (- line-min current-line)))
+ (while (and (<= i0 i-max) (< (aref data i0) skip-lines))
+ (setq skip-lines (- skip-lines (aref data i0)))
+ (setq i0 (+ i0 5)))
+ (setq current-line (- line-min skip-lines)))
+ (forward-line (- current-line line-min))
+ (setq line-start-pos (point))
+ (cl-loop
+ for i from i0 to i-max by 5 do
+ (setq line-delta (aref data i))
+ (unless (= line-delta 0)
+ (forward-line line-delta)
+ (setq line-start-pos (point))
+ (setq column 0)
+ (setq current-line (+ current-line line-delta)))
+ (setq column (+ column (aref data (1+ i))))
+ (setq face (aref faces (aref data (+ i 3))))
+ (setq text-property-beg (+ line-start-pos column))
+ (setq text-property-end (+ text-property-beg (aref data (+ i 2))))
+ (when face
+ (put-text-property text-property-beg text-property-end 'face face))
+ (cl-loop for j from 0 to (1- (length modifier-faces)) do
+ (when (and (aref modifier-faces j)
+ (> (logand (aref data (+ i 4)) (lsh 1 j)) 0))
+ (add-face-text-property text-property-beg text-property-end
+ (aref modifier-faces j))))
+ when (> current-line line-max-inclusive) return nil)))))
+ (let ((token-region (plist-get lsp--semantic-tokens-cache :_region)))
+ (if token-region
+ `(jit-lock-bounds ,(max beg (car token-region)) . ,(min end (cdr token-region)))
+ `(jit-lock-bounds ,beg . ,end)))))))
+
+(defun lsp-semantic-tokens--request-update ()
+ "Request semantic-tokens update."
+ (lsp--semantic-tokens-request (cons (window-start) (window-end)) t))
+
+(defun lsp--semantic-tokens-as-defined-by-workspace (workspace)
+ "Return plist of token-types and token-modifiers defined by WORKSPACE, or nil if none are defined."
+ (when-let ((token-capabilities
+ (or
+ (-some->
+ (lsp--registered-capability "textDocument/semanticTokens")
+ (lsp--registered-capability-options))
+ (lsp:server-capabilities-semantic-tokens-provider?
+ (lsp--workspace-server-capabilities workspace)))))
+ (-let* (((&SemanticTokensOptions :legend) token-capabilities))
+ `(:token-types ,(lsp:semantic-tokens-legend-token-types legend)
+ :token-modifiers ,(lsp:semantic-tokens-legend-token-modifiers legend)))))
+
+(defun lsp-semantic-tokens-suggest-overrides ()
+ "Suggest face overrides that best match the faces chosen by `font-lock-fontify-region'."
+ (interactive)
+ (-when-let* ((token-info (-some #'lsp--semantic-tokens-as-defined-by-workspace lsp--buffer-workspaces))
+ ((&plist :token-types token-types :token-modifiers token-modifiers) token-info))
+ (let* ((tokens (lsp-request
+ "textDocument/semanticTokens/full"
+ `(:textDocument, (lsp--text-document-identifier))))
+ (inhibit-field-text-motion t)
+ (data (lsp-get tokens :data))
+ (associated-faces '())
+ (line-delta)
+ ;; KLUDGE: clear cache so our font-lock advice won't apply semantic-token faces
+ (old-cache lsp--semantic-tokens-cache)
+ (face-or-faces))
+ (setq lsp--semantic-tokens-cache nil)
+ (save-restriction
+ (save-excursion
+ (widen)
+ (font-lock-fontify-region (point-min) (point-max) t)
+ (save-mark-and-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (cl-loop
+ for i from 0 to (1- (length data)) by 5 do
+ (setq line-delta (aref data i))
+ (unless (= line-delta 0) (forward-line line-delta))
+ (forward-char (aref data (+ i 1)))
+ (setq face-or-faces (get-text-property (point) 'face))
+ ;; TODO: consider modifiers?
+ (when face-or-faces
+ (--each (if (listp face-or-faces) face-or-faces (list face-or-faces))
+ (cl-pushnew `(,(aref data (+ i 3)) . ,it) associated-faces :test #'equal))))
+ (setq lsp--semantic-tokens-cache old-cache)
+ (font-lock-flush)))))
+ (switch-to-buffer (get-buffer-create "*Suggested Overrides*"))
+ (insert "(")
+ ;; TODO: sort alternatives by frequency
+ (--each-indexed (-group-by #'car associated-faces)
+ (insert (if (= it-index 0) "(" "\n ("))
+ (insert (format "%s . " (aref token-types (car it))))
+ (--each-indexed (mapcar #'cdr (cdr it))
+ (insert (if (= it-index 0) (format "%s)" (prin1-to-string it))
+ (format " ; Alternative: %s" (prin1-to-string it))))))
+ (insert ")"))))
+
+
+;;;###autoload
+(defun lsp--semantic-tokens-initialize-buffer ()
+ "Initialize the buffer for semantic tokens.
+IS-RANGE-PROVIDER is non-nil when server supports range requests."
+ (let* ((old-extend-region-functions font-lock-extend-region-functions)
+ ;; make sure font-lock always fontifies entire lines (TODO: do we also have
+ ;; to change some jit-lock-...-region functions/variables?)
+ (new-extend-region-functions
+ (if (memq 'font-lock-extend-region-wholelines old-extend-region-functions)
+ old-extend-region-functions
+ (cons 'font-lock-extend-region-wholelines old-extend-region-functions))))
+ (setq lsp--semantic-tokens-cache nil)
+ (setq font-lock-extend-region-functions new-extend-region-functions)
+ (add-function :around (local 'font-lock-fontify-region-function) #'lsp-semantic-tokens--fontify)
+ (add-hook 'lsp-on-change-hook #'lsp-semantic-tokens--request-update nil t)
+ (lsp-semantic-tokens--request-update)
+ (setq lsp--semantic-tokens-teardown
+ (lambda ()
+ (setq font-lock-extend-region-functions old-extend-region-functions)
+ (when lsp--semantic-tokens-idle-timer
+ (cancel-timer lsp--semantic-tokens-idle-timer)
+ (setq lsp--semantic-tokens-idle-timer nil))
+ (setq lsp--semantic-tokens-cache nil)
+ (remove-function (local 'font-lock-fontify-region-function)
+ #'lsp-semantic-tokens--fontify)
+ (remove-hook 'lsp-on-change-hook #'lsp-semantic-tokens--request-update t)))))
+
+(defun lsp--semantic-tokens-build-face-map (identifiers faces category varname)
+ "Build map of FACES for IDENTIFIERS using CATEGORY and VARNAME."
+ (apply 'vector
+ (mapcar (lambda (id)
+ (let ((maybe-face (cdr (assoc id faces))))
+ (when (and lsp-semantic-tokens-warn-on-missing-face (not maybe-face))
+ (lsp-warn "No face has been associated to the %s '%s': consider adding a corresponding definition to %s"
+ category id varname)) maybe-face)) identifiers)))
+
+(defun lsp-semantic-tokens--replace-alist-values (a b)
+ "Replace alist A values with B ones where available."
+ (-map
+ (-lambda ((ak . av))
+ (cons ak (alist-get ak b av nil #'string=)))
+ a))
+
+(defun lsp-semantic-tokens--type-faces-for (client)
+ "Return the semantic token type faces for CLIENT."
+ (lsp-semantic-tokens--replace-alist-values lsp-semantic-token-faces
+ (plist-get (lsp--client-semantic-tokens-faces-overrides client) :types)))
+
+(defun lsp-semantic-tokens--modifier-faces-for (client)
+ "Return the semantic token type faces for CLIENT."
+ (lsp-semantic-tokens--replace-alist-values lsp-semantic-token-modifier-faces
+ (plist-get (lsp--client-semantic-tokens-faces-overrides client) :modifiers)))
+
+(defun lsp--semantic-tokens-on-refresh ()
+ "Invoked in response to workspace/semanticTokens/refresh requests."
+ (cl-loop for workspace in (lsp-workspaces)
+ for ws-buffer in (lsp--workspace-buffers workspace) do
+ (unless (equal (current-buffer) ws-buffer)
+ (setf (buffer-local-value 'lsp--semantic-tokens-cache ws-buffer) nil)))
+ (lsp--semantic-tokens-request-full-token-set-when-idle t))
+
+;;;###autoload
+(defun lsp--semantic-tokens-initialize-workspace (workspace)
+ "Initialize semantic tokens for WORKSPACE."
+ (cl-assert workspace)
+ (-let (((&plist :token-types types :token-modifiers modifiers)
+ (lsp--semantic-tokens-as-defined-by-workspace workspace))
+ (client (lsp--workspace-client workspace)))
+ (setf (lsp--workspace-semantic-tokens-faces workspace)
+ (lsp--semantic-tokens-build-face-map
+ types (lsp-semantic-tokens--type-faces-for client)
+ "semantic token" "lsp-semantic-token-faces"))
+ (setf (lsp--workspace-semantic-tokens-modifier-faces workspace)
+ (lsp--semantic-tokens-build-face-map
+ modifiers (lsp-semantic-tokens--modifier-faces-for client)
+ "semantic token modifier" "lsp-semantic-token-modifier-faces"))))
+
+;;;###autoload
+(defun lsp-semantic-tokens--warn-about-deprecated-setting ()
+ "Warn about deprecated semantic highlighting variable."
+ (when (boundp 'lsp-semantic-highlighting)
+ (pcase lsp-semantic-highlighting
+ (:semantic-tokens
+ (lsp-warn "It seems you wish to use semanticTokens-based
+ highlighting. To do so, please remove any references to the
+ deprecated variable `lsp-semantic-highlighting' from your
+ configuration and set `lsp-semantic-tokens-enable' to `t'
+ instead.")
+ (setq lsp-semantic-tokens-enable t))
+ ((or :immediate :deferred)
+ (lsp-warn "It seems you wish to use Theia-based semantic
+ highlighting. This protocol has been superseded by the
+ semanticTokens protocol specified by LSP v3.16 and is no longer
+ supported by lsp-mode. If your language server provides
+ semanticToken support, please set
+ `lsp-semantic-tokens-enable' to `t' to use it.")))))
+
+;;;###autoload
+(defun lsp-semantic-tokens--enable ()
+ "Enable semantic tokens mode."
+ (when (and lsp-semantic-tokens-enable
+ (lsp-feature? "textDocument/semanticTokens"))
+ (lsp-semantic-tokens--warn-about-deprecated-setting)
+ (lsp-semantic-tokens-mode 1)
+ (mapc #'lsp--semantic-tokens-initialize-workspace
+ (lsp--find-workspaces-for "textDocument/semanticTokens"))
+ (lsp--semantic-tokens-initialize-buffer)))
+
+(defun lsp-semantic-tokens--disable ()
+ "Disable semantic tokens mode."
+ (lsp-semantic-tokens-mode -1))
+
+;;;###autoload
+(define-minor-mode lsp-semantic-tokens-mode
+ "Toggle semantic-tokens support."
+ :group 'lsp-semantic-tokens
+ :global nil
+ (cond
+ (lsp-semantic-tokens-mode
+ (add-hook 'lsp-configure-hook #'lsp-semantic-tokens--enable nil t)
+ (add-hook 'lsp-unconfigure-hook #'lsp-semantic-tokens--disable nil t)
+ (lsp--semantic-tokens-initialize-buffer))
+ (t
+ (remove-hook 'lsp-configure-hook #'lsp-semantic-tokens--enable t)
+ (remove-hook 'lsp-unconfigure-hook #'lsp-semantic-tokens--disable t)
+ (when lsp--semantic-tokens-teardown
+ (funcall lsp--semantic-tokens-teardown))
+ (lsp-semantic-tokens--request-update)
+ (setq lsp--semantic-tokens-idle-timer nil
+ lsp--semantic-tokens-cache nil
+ lsp--semantic-tokens-teardown nil))))
+
+;; debugging helpers
+(defun lsp--semantic-tokens-verify ()
+ "Store current token set and compare with the response to a full token request."
+ (interactive)
+ (let ((old-tokens (--> lsp--semantic-tokens-cache (plist-get it :response) (lsp-get it :data)))
+ (old-version (--> lsp--semantic-tokens-cache (plist-get it :_documentVersion))))
+ (if (not (equal lsp--cur-version old-version))
+ (message "Stored documentVersion %d differs from current version %d" old-version lsp--cur-version)
+ (lsp-request-async
+ "textDocument/semanticTokens/full" `(:textDocument ,(lsp--text-document-identifier))
+ (lambda (response)
+ (let ((new-tokens (lsp-get response :data)))
+ (if (equal old-tokens new-tokens)
+ (message "New tokens (total count %d) are identical to previously held token set"
+ (length new-tokens))
+ (message "Newly returned tokens differ from old token set")
+ (print old-tokens)
+ (print new-tokens))))
+ :mode 'tick
+ :cancel-token (format "semantic-tokens-%s" (lsp--buffer-uri))))))
+
+(defvar-local lsp-semantic-tokens--log '())
+
+(defvar-local lsp-semantic-tokens--prev-response nil)
+
+(defun lsp-semantic-tokens--log-buffer-contents (tag)
+ "Log buffer contents for TAG."
+ (save-restriction
+ (save-excursion
+ (widen) (push `(:tag ,tag
+ :buffer-contents ,(buffer-substring (point-min) (point-max))
+ :prev-response ,lsp-semantic-tokens--prev-response)
+ lsp-semantic-tokens--log))))
+
+(defun lsp-semantic-tokens-enable-log ()
+ "Enable logging of intermediate fontification states.
+
+This is a debugging tool, and may incur significant performance penalties."
+ (setq lsp-semantic-tokens--log '())
+ (defadvice lsp-semantic-tokens--fontify (around advice-tokens-fontify activate)
+ (lsp-semantic-tokens--log-buffer-contents 'before)
+ (let ((result ad-do-it))
+ (lsp-semantic-tokens--log-buffer-contents 'after)
+ result))
+ (defadvice lsp--semantic-tokens-ingest-full/delta-response
+ (before log-delta-response (response) activate)
+ (setq lsp-semantic-tokens--prev-response `(:request-type "delta"
+ :response ,response
+ :version ,lsp--cur-version)))
+ (defadvice lsp--semantic-tokens-ingest-full-response
+ (before log-full-response (response) activate)
+ (setq lsp-semantic-tokens--prev-response `(:request-type "full"
+ :response ,response
+ :version ,lsp--cur-version)))
+ (defadvice lsp--semantic-tokens-ingest-range-response
+ (before log-range-response (response) activate)
+ (setq lsp-semantic-tokens--prev-response `(:request-type "range"
+ :response ,response
+ :version ,lsp--cur-version))))
+
+(defun lsp-semantic-tokens-disable-log ()
+ "Disable logging of intermediate fontification states."
+ (ad-unadvise 'lsp-semantic-tokens--fontify)
+ (ad-unadvise 'lsp--semantic-tokens-ingest-full/delta-response)
+ (ad-unadvise 'lsp--semantic-tokens-ingest-full-response)
+ (ad-unadvise 'lsp--semantic-tokens-ingest-range-response))
+
+(declare-function htmlize-buffer "ext:htmlize")
+
+(defun lsp-semantic-tokens-export-log ()
+ "Write HTML-formatted snapshots of previous fontification results to /tmp."
+ (require 'htmlize)
+ (let* ((outdir (f-join "/tmp" "semantic-token-snapshots"))
+ (progress-reporter
+ (make-progress-reporter
+ (format "Writing buffer snapshots to %s..." outdir)
+ 0 (length lsp-semantic-tokens--log))))
+ (f-mkdir outdir)
+ (--each-indexed (reverse lsp-semantic-tokens--log)
+ (-let* (((&plist :tag tag
+ :buffer-contents buffer-contents
+ :prev-response prev-response) it)
+ (html-buffer))
+ ;; FIXME: doesn't update properly; sit-for helps... somewhat,
+ ;; but unreliably
+ (when (= (% it-index 5) 0)
+ (progress-reporter-update progress-reporter it-index)
+ (sit-for 0.01))
+ ;; we're emitting 2 snapshots (before & after) per update, so request
+ ;; parameters should only change on every 2nd invocation
+ (when (cl-evenp it-index)
+ (with-temp-buffer
+ (insert (prin1-to-string prev-response))
+ (write-file (f-join outdir (format "parameters_%d.el" (/ it-index 2))))))
+ (with-temp-buffer
+ (insert buffer-contents)
+ (setq html-buffer (htmlize-buffer))
+ (with-current-buffer html-buffer
+ ;; some configs such as emacs-doom may autoformat on save; switch to
+ ;; fundamental-mode to avoid this
+ (fundamental-mode)
+ (write-file (f-join outdir (format "buffer_%d_%s.html" (/ it-index 2) tag)))))
+ (kill-buffer html-buffer)))
+ (progress-reporter-done progress-reporter)))
+
+(lsp-consistency-check lsp-semantic-tokens)
+
+(provide 'lsp-semantic-tokens)
+;;; lsp-semantic-tokens.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-solargraph.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-solargraph.el
new file mode 100644
index 0000000..968b32a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-solargraph.el
@@ -0,0 +1,166 @@
+;;; lsp-solargraph.el --- Solargraph server configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-solargraph nil
+ "LSP support for Ruby, using the Solargraph language server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/castwide/solargraph")
+ :package-version '(lsp-mode . "6.1"))
+
+;; (defcustom lsp-solargraph-check-gem-version t
+;; "Automatically check if a new version of the Solargraph gem is available."
+;; :type 'boolean)
+
+(defcustom lsp-solargraph-completion t
+ "Enable completion"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-hover t
+ "Enable hover"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-diagnostics t
+ "Enable diagnostics"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-autoformat nil
+ "Enable automatic formatting while typing (WARNING: experimental)"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-formatting t
+ "Enable document formatting"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-symbols t
+ "Enable symbols"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-definitions t
+ "Enable definitions (go to, etc.)"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-rename t
+ "Enable symbol renaming"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-references t
+ "Enable finding references"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-folding t
+ "Enable folding ranges"
+ :type 'boolean
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-log-level "warn"
+ "Level of debug info to log. `warn` is least and `debug` is most."
+ :type '(choice (const :tag "warn" "info" "debug"))
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+;; https://github.com/castwide/solargraph#solargraph-and-bundler
+(defcustom lsp-solargraph-use-bundler nil
+ "Run solargraph under bundler"
+ :type 'boolean
+ :safe #'booleanp
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-solargraph-multi-root t
+ "If non nil, `solargraph' will be started in multi-root mode."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-solargraph-library-directories
+ '("~/.rbenv/" "/usr/lib/ruby/" "~/.rvm/" "~/.gem/")
+ "List of directories which will be considered to be libraries."
+ :type '(repeat string)
+ :group 'lsp-solargraph
+ :package-version '(lsp-mode . "7.0.1"))
+
+(defun lsp-solargraph--build-command ()
+ "Build solargraph command"
+ (let ((lsp-command '("solargraph" "stdio")))
+ (if lsp-solargraph-use-bundler
+ (append '("bundle" "exec") lsp-command)
+ lsp-command)))
+
+(lsp-register-custom-settings
+ '(("solargraph.logLevel" lsp-solargraph-log-level)
+ ("solargraph.folding" lsp-solargraph-folding t)
+ ("solargraph.references" lsp-solargraph-references t)
+ ("solargraph.rename" lsp-solargraph-rename t)
+ ("solargraph.definitions" lsp-solargraph-definitions t)
+ ("solargraph.symbols" lsp-solargraph-symbols t)
+ ("solargraph.formatting" lsp-solargraph-formatting t)
+ ("solargraph.autoformat" lsp-solargraph-autoformat t)
+ ("solargraph.diagnostics" lsp-solargraph-diagnostics t)
+ ("solargraph.hover" lsp-solargraph-hover t)
+ ("solargraph.completion" lsp-solargraph-completion t)
+ ("solargraph.useBundler" lsp-solargraph-use-bundler t)))
+
+;; Ruby
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ #'lsp-solargraph--build-command)
+ :major-modes '(ruby-mode enh-ruby-mode)
+ :priority -1
+ :multi-root lsp-solargraph-multi-root
+ :library-folders-fn (lambda (_workspace) lsp-solargraph-library-directories)
+ :server-id 'ruby-ls
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "solargraph"))))))
+
+(lsp-consistency-check lsp-solargraph)
+
+(provide 'lsp-solargraph)
+;;; lsp-solargraph.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sorbet.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sorbet.el
new file mode 100644
index 0000000..f11ab47
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sorbet.el
@@ -0,0 +1,59 @@
+;;; lsp-sorbet.el --- Sorbet server configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020
+
+;; Author: Christopher Wilson <chris@sencjw.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; lsp-sorbet client
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-sorbet nil
+ "LSP support for Ruby, using the Sorbet language server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/sorbet/sorbet")
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-sorbet-use-bundler nil
+ "Run sorbet under bundler"
+ :type 'boolean
+ :group 'lsp-sorbet
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defun lsp-sorbet--build-command ()
+ "Build sorbet command"
+ (let ((lsp-command '("srb" "typecheck" "--lsp" "--disable-watchman")))
+ (if lsp-sorbet-use-bundler
+ (append '("bundle" "exec") lsp-command)
+ lsp-command)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ #'lsp-sorbet--build-command)
+ :priority -2
+ :major-modes '(ruby-mode enh-ruby-mode)
+ :server-id 'sorbet-ls))
+
+(lsp-consistency-check lsp-sorbet)
+
+(provide 'lsp-sorbet)
+;;; lsp-sorbet.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sqls.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sqls.el
new file mode 100644
index 0000000..72ad70a
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-sqls.el
@@ -0,0 +1,190 @@
+;;; lsp-sqls.el --- SQL Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Shunya Ishii
+
+;; Author: Shunya Ishii
+;; Keywords: sql lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for SQL
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-sqls nil
+ "LSP support for SQL, using sqls"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/lighttiger2505/sqls")
+ :package-version `(lsp-mode . "7.0"))
+
+(defcustom lsp-sqls-server "sqls"
+ "Path to the `sqls` binary."
+ :group 'lsp-sqls
+ :risky t
+ :type 'file
+ :package-version `(lsp-mode . "7.0"))
+
+(defcustom lsp-sqls-workspace-config-path "workspace"
+ "If non-nil then setup workspace configuration with json file path."
+ :group 'lsp-sqls
+ :risky t
+ :type '(choice (const "workspace")
+ (const "root"))
+ :package-version `(lsp-mode . "7.0"))
+
+(defun lsp-sqls--make-launch-cmd ()
+ (-let [base `(,lsp-sqls-server)]
+ ;; we can add some options to command. (e.g. "-config")
+ base))
+
+
+(defcustom lsp-sqls-timeout 0.5
+ "Timeout to use for `sqls' requests."
+ :type 'number
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-sqls-connections nil
+ "The connections to the SQL server(s)."
+ :type '(repeat (alist :key-type (choice
+ (const :tag "Driver" driver)
+ (const :tag "Connection String" dataSourceName))
+ :value-type string)))
+
+(defun lsp-sqls-setup-workspace-configuration ()
+ "Setup workspace configuration using json file depending on `lsp-sqls-workspace-config-path'."
+
+ (if lsp-sqls-connections
+ (lsp--set-configuration `(:sqls (:connections ,(apply #'vector lsp-sqls-connections))))
+ (when-let ((config-json-path (cond
+ ((equal lsp-sqls-workspace-config-path "workspace")
+ ".sqls/config.json")
+ ((equal lsp-sqls-workspace-config-path "root")
+ (-> (lsp-workspace-root)
+ (f-join ".sqls/config.json"))))))
+ (when (file-exists-p config-json-path)
+ (lsp--set-configuration (lsp--read-json-file config-json-path))))))
+
+(defun lsp-sqls--show-results (result)
+ (with-current-buffer (get-buffer-create "*sqls results*")
+ (with-help-window (buffer-name)
+ (erase-buffer)
+ (insert result))))
+
+(defun lsp-sql-execute-query (&optional command start end)
+ "Execute COMMAND on buffer text against current database.
+Buffer text is between START and END. If START and END are nil,
+use the current region if set, otherwise the entire buffer."
+ (interactive)
+ (lsp-sqls--show-results
+ (lsp-request
+ "workspace/executeCommand"
+ (list :command "executeQuery"
+ :arguments (or
+ (when command
+ (lsp:command-arguments? command))
+ (vector (lsp--buffer-uri)))
+ :timeout lsp-sqls-timeout
+ :range (list
+ :start (lsp--point-to-position
+ (cond
+ (start start)
+ ((use-region-p) (region-beginning))
+ (t (point-min))))
+ :end (lsp--point-to-position
+ (cond
+ (end end)
+ ((use-region-p) (region-end))
+ (t (point-max)))))))))
+
+(defun lsp-sql-execute-paragraph (&optional command)
+ "Execute COMMAND on paragraph against current database."
+ (interactive)
+ (let ((start (save-excursion (backward-paragraph) (point)))
+ (end (save-excursion (forward-paragraph) (point))))
+ (lsp-sql-execute-query command start end)))
+
+(defun lsp-sql-show-databases (&optional _command)
+ "Show databases."
+ (interactive)
+ (lsp-sqls--show-results
+ (lsp-request
+ "workspace/executeCommand"
+ (list :command "showDatabases" :timeout lsp-sqls-timeout))))
+
+(defun lsp-sql-show-schemas (&optional _command)
+ "Show schemas."
+ (interactive)
+ (lsp-sqls--show-results
+ (lsp-request
+ "workspace/executeCommand"
+ (list :command "showSchemas" :timeout lsp-sqls-timeout))))
+
+(defun lsp-sql-show-connections (&optional _command)
+ "Show connections."
+ (interactive)
+ (lsp-sqls--show-results
+ (lsp-request
+ "workspace/executeCommand"
+ (list :command "showConnections" :timeout lsp-sqls-timeout))))
+
+(defun lsp-sql-switch-database (&optional _command)
+ "Switch database."
+ (interactive)
+ (lsp-workspace-command-execute
+ "switchDatabase"
+ (vector (completing-read
+ "Select database: "
+ (s-lines (lsp-workspace-command-execute "showDatabases"))
+ nil
+ t))))
+
+(defun lsp-sql-switch-connection (&optional _command)
+ "Switch connection."
+ (interactive)
+ (lsp-workspace-command-execute
+ "switchConnections"
+ (vector (cl-first
+ (s-match "\\([[:digit:]]*\\)"
+ (completing-read
+ "Select connection: "
+ (s-lines (lsp-workspace-command-execute "showConnections"))
+ nil
+ t))))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection #'lsp-sqls--make-launch-cmd)
+ :major-modes '(sql-mode)
+ :priority -1
+ :action-handlers (ht ("executeQuery" #'lsp-sql-execute-query)
+ ("showDatabases" #'lsp-sql-show-databases)
+ ("showSchemas" #'lsp-sql-show-schemas)
+ ("showConnections" #'lsp-sql-show-connections)
+ ("switchDatabase" #'lsp-sql-switch-database)
+ ("switchConnections" #'lsp-sql-switch-connection))
+ :server-id 'sqls
+ :initialized-fn (lambda (workspace)
+ (-> workspace
+ (lsp--workspace-server-capabilities)
+ (lsp:set-server-capabilities-execute-command-provider? t))
+ (with-lsp-workspace workspace
+ (lsp-sqls-setup-workspace-configuration)))))
+
+(lsp-consistency-check lsp-sqls)
+
+(provide 'lsp-sqls)
+;;; lsp-sqls.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-steep.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-steep.el
new file mode 100644
index 0000000..f1ecba4
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-steep.el
@@ -0,0 +1,73 @@
+;;; lsp-steep.el --- lsp-mode for Steep -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Masafumi Koba
+
+;; Author: Masafumi Koba <ybiquitous@gmail.com>
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for Steep which is a Ruby type checker.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-steep nil
+ "LSP support for Steep, using the Steep language server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/soutaro/steep"))
+
+(defcustom lsp-steep-log-level "warn"
+ "Log level of Steep."
+ :type '(choice
+ (const "fatal")
+ (const "error")
+ (const "warn")
+ (const "info")
+ (const "debug"))
+ :group 'lsp-steep)
+
+(defcustom lsp-steep-use-bundler t
+ "Run Steep using Bunder."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'lsp-steep)
+
+(defcustom lsp-steep-server-path nil
+ "Path of the Steep language server executable.
+If specified, `lsp-steep-use-bundler' is ignored."
+ :type 'file
+ :group 'lsp-steep
+ :package-version '(lsp-mode . "7.1"))
+
+(defun lsp-steep--build-command ()
+ "Build a command to start the Steep language server."
+ (append
+ (if (and lsp-steep-use-bundler (not lsp-steep-server-path)) '("bundle" "exec"))
+ (list (or lsp-steep-server-path "steep") "langserver" "--log-level" lsp-steep-log-level)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection #'lsp-steep--build-command)
+ :major-modes '(ruby-mode enh-ruby-mode)
+ :priority -3
+ :server-id 'steep-ls))
+
+(lsp-consistency-check lsp-steep)
+
+(provide 'lsp-steep)
+;;; lsp-steep.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-svelte.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-svelte.el
new file mode 100644
index 0000000..47f4c8e
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-svelte.el
@@ -0,0 +1,307 @@
+;;; lsp-svelte.el --- LSP Svelte integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Stepan Lusnikov
+
+;; Author: Stepan Lusnikov <endenwer@gmail.com>
+;; Keywords: lsp svelte
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for Svelte
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-svelte nil
+ "LSP support for Svelte."
+ :group 'lsp-mode
+ :link '(url-link
+ "https://github.com/sveltejs/language-tools"))
+
+(lsp-dependency 'svelte-language-server
+ '(:system "svelteserver")
+ '(:npm :package "svelte-language-server"
+ :path "svelteserver"))
+
+(defcustom lsp-svelte-plugin-typescript-enable t
+ "Enable the TypeScript plugin"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-diagnostics-enable t
+ "Enable diagnostic messages for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-hover-enable t
+ "Enable hover info for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-document-symbols-enable t
+ "Enable document symbols for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-completions-enable t
+ "Enable completions for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-find-references-enable t
+ "Enable find-references for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-definitions-enable t
+ "Enable go to definition for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-code-actions-enable t
+ "Enable code actions for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-selection-range-enable t
+ "Enable selection range for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-signature-help-enable t
+ "Enable signature help (parameter hints) for TypeScript"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-typescript-rename-enable t
+ "Enable rename functionality for JS/TS variables inside Svelte files"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-enable t
+ "Enable the CSS plugin"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-globals ""
+ "Which css files should be checked for global variables
+(`--global-var: value;`).
+
+These variables are added to the css completions. String of comma-separated
+file paths or globs relative to workspace root."
+ :type 'string
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-diagnostics-enable t
+ "Enable diagnostic messages for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-hover-enable t
+ "Enable hover info for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-completions-enable t
+ "Enable auto completions for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-completions-emmet t
+ "Enable emmet auto completions for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-document-colors-enable t
+ "Enable document colors for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-color-presentations-enable t
+ "Enable color picker for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-document-symbols-enable t
+ "Enable document symbols for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-css-selection-range-enable t
+ "Enable selection range for CSS"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-enable t
+ "Enable the HTML plugin"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-hover-enable t
+ "Enable hover info for HTML"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-completions-enable t
+ "Enable auto completions for HTML"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-completions-emmet t
+ "Enable emmet auto completions for HTML"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-tag-complete-enable t
+ "Enable HTML tag auto closing"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-html-document-symbols-enable t
+ "Enable document symbols for HTML"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-enable t
+ "Enable the Svelte plugin"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-diagnostics-enable t
+ "Enable diagnostic messages for Svelte"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-compiler-warnings nil
+ "Svelte compiler warning codes to ignore or to treat as errors.
+Example: '((css-unused-selector . ignore) (unused-export-let . error))"
+ :type '(alist :key-type (symbol :tag "Warning code")
+ :value-type (choice
+ (const :tag "Ignore" ignore)
+ (const :tag "Treat as error" error)))
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-format-enable t
+ "Enable formatting for Svelte (includes css & js)"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-completions-enable t
+ "Enable auto completions for Svelte"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-hover-enable t
+ "Enable hover information for Svelte"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-code-actions-enable t
+ "Enable Code Actions for Svelte"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-selection-range-enable t
+ "Enable selection range for Svelte"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(defcustom lsp-svelte-plugin-svelte-rename-enable t
+ "Enable rename/move Svelte files functionality"
+ :type 'boolean
+ :package-version '(lsp-mode . "7.1.0"))
+
+(lsp-register-custom-settings
+ '(("svelte.plugin.svelte.rename.enable" lsp-svelte-plugin-svelte-rename-enable t)
+ ("svelte.plugin.svelte.selectionRange.enable" lsp-svelte-plugin-svelte-selection-range-enable t)
+ ("svelte.plugin.svelte.codeActions.enable" lsp-svelte-plugin-svelte-code-actions-enable t)
+ ("svelte.plugin.svelte.hover.enable" lsp-svelte-plugin-svelte-hover-enable t)
+ ("svelte.plugin.svelte.completions.enable" lsp-svelte-plugin-svelte-completions-enable t)
+ ("svelte.plugin.svelte.format.enable" lsp-svelte-plugin-svelte-format-enable t)
+ ("svelte.plugin.svelte.compilerWarnings" lsp-svelte-plugin-svelte-compiler-warnings)
+ ("svelte.plugin.svelte.diagnostics.enable" lsp-svelte-plugin-svelte-diagnostics-enable t)
+ ("svelte.plugin.svelte.enable" lsp-svelte-plugin-svelte-enable t)
+ ("svelte.plugin.html.documentSymbols.enable" lsp-svelte-plugin-html-document-symbols-enable t)
+ ("svelte.plugin.html.tagComplete.enable" lsp-svelte-plugin-html-tag-complete-enable t)
+ ("svelte.plugin.html.completions.emmet" lsp-svelte-plugin-html-completions-emmet t)
+ ("svelte.plugin.html.completions.enable" lsp-svelte-plugin-html-completions-enable t)
+ ("svelte.plugin.html.hover.enable" lsp-svelte-plugin-html-hover-enable t)
+ ("svelte.plugin.html.enable" lsp-svelte-plugin-html-enable t)
+ ("svelte.plugin.css.selectionRange.enable" lsp-svelte-plugin-css-selection-range-enable t)
+ ("svelte.plugin.css.documentSymbols.enable" lsp-svelte-plugin-css-document-symbols-enable t)
+ ("svelte.plugin.css.colorPresentations.enable" lsp-svelte-plugin-css-color-presentations-enable t)
+ ("svelte.plugin.css.documentColors.enable" lsp-svelte-plugin-css-document-colors-enable t)
+ ("svelte.plugin.css.completions.emmet" lsp-svelte-plugin-css-completions-emmet t)
+ ("svelte.plugin.css.completions.enable" lsp-svelte-plugin-css-completions-enable t)
+ ("svelte.plugin.css.hover.enable" lsp-svelte-plugin-css-hover-enable t)
+ ("svelte.plugin.css.diagnostics.enable" lsp-svelte-plugin-css-diagnostics-enable t)
+ ("svelte.plugin.css.globals" lsp-svelte-plugin-css-globals)
+ ("svelte.plugin.css.enable" lsp-svelte-plugin-css-enable t)
+ ("svelte.plugin.typescript.rename.enable" lsp-svelte-plugin-typescript-rename-enable t)
+ ("svelte.plugin.typescript.signatureHelp.enable" lsp-svelte-plugin-typescript-signature-help-enable t)
+ ("svelte.plugin.typescript.selectionRange.enable" lsp-svelte-plugin-typescript-selection-range-enable t)
+ ("svelte.plugin.typescript.codeActions.enable" lsp-svelte-plugin-typescript-code-actions-enable t)
+ ("svelte.plugin.typescript.definitions.enable" lsp-svelte-plugin-typescript-definitions-enable t)
+ ("svelte.plugin.typescript.findReferences.enable" lsp-svelte-plugin-typescript-find-references-enable t)
+ ("svelte.plugin.typescript.completions.enable" lsp-svelte-plugin-typescript-completions-enable t)
+ ("svelte.plugin.typescript.documentSymbols.enable" lsp-svelte-plugin-typescript-document-symbols-enable t)
+ ("svelte.plugin.typescript.hover.enable" lsp-svelte-plugin-typescript-hover-enable t)
+ ("svelte.plugin.typescript.diagnostics.enable" lsp-svelte-plugin-typescript-diagnostics-enable t)
+ ("svelte.plugin.typescript.enable" lsp-svelte-plugin-typescript-enable t)))
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(lsp-package-path 'svelte-language-server)
+ "--stdio")))
+ :activation-fn (lambda (file-name _mode)
+ (string= (f-ext file-name)
+ "svelte"))
+ :initialization-options
+ (lambda ()
+ (list :config (ht-get* (lsp-configuration-section "svelte.plugin")
+ "svelte"
+ "plugin")
+ :prettierConfig (lsp-configuration-section "prettier")
+ :emmetConfig (lsp-configuration-section "emmet")
+ :typescriptConfig: (list :typescript (lsp-configuration-section "typescript")
+ :javascript (lsp-configuration-section "javascript"))
+ :dontFilterIncompleteCompletions t))
+ :server-id 'svelte-ls
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'svelte-language-server callback error-callback))
+ :initialized-fn
+ (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (ht-merge (lsp-configuration-section "svelte")
+ (lsp-configuration-section "javascript")
+ (lsp-configuration-section "typescript")))
+ (lsp--server-register-capability
+ (lsp-make-registration
+ :id "js/ts/id"
+ :method "workspace/didChangeWatchedFiles"
+ :register-options? (lsp-make-did-change-watched-files-registration-options
+ :watchers
+ (vector (lsp-make-file-system-watcher :glob-pattern "**/*.js")
+ (lsp-make-file-system-watcher :glob-pattern "**/*.ts")))))))))
+
+(lsp-consistency-check lsp-svelte)
+
+(provide 'lsp-svelte)
+;;; lsp-svelte.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-terraform.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-terraform.el
new file mode 100644
index 0000000..af215f4
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-terraform.el
@@ -0,0 +1,68 @@
+;;; lsp-terraform.el --- Terraform Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ross Donaldson
+
+;; Author: Ross Donaldson
+;; Keywords: terraform lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for Terraform
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-terraform nil
+ "LSP support for Terraform, using terraform-lsp"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/juliosueiras/terraform-lsp")
+ :package-version `(lsp-mode . "6.2"))
+
+(defcustom lsp-terraform-server "terraform-lsp"
+ "Path to the `terraform-lsp' binary."
+ :group 'lsp-terraform
+ :risky t
+ :type '(choice
+ (file :tag "File")
+ (repeat string))
+ :package-version `(lsp-mode . "6.2"))
+
+(defcustom lsp-terraform-enable-logging nil
+ "If non-nil, enable `terraform-ls''s native logging."
+ :group 'lsp-terraform
+ :risky t
+ :type 'boolean
+ :package-version `(lsp-mode . "6.2"))
+
+(defun lsp-terraform--make-launch-cmd ()
+ (-let [base (if (stringp lsp-terraform-server)
+ `(,lsp-terraform-server)
+ lsp-terraform-server)]
+ (when lsp-terraform-enable-logging
+ (push "-enable-log-file" base))
+ base))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection #'lsp-terraform--make-launch-cmd)
+ :major-modes '(terraform-mode)
+ :priority -1
+ :server-id 'tfls))
+
+(lsp-consistency-check lsp-terraform)
+
+(provide 'lsp-terraform)
+;;; lsp-terraform.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-tex.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-tex.el
new file mode 100644
index 0000000..3cd6d08
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-tex.el
@@ -0,0 +1,68 @@
+;;; lsp-tex.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, tex
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the Tex Typesetting Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-tex nil
+ "LSP support for TeX and friends, using Digestif and texlab."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/astoff/digestif/")
+ :link '(url-link "https://github.com/latex-lsp/texlab"))
+
+(defcustom lsp-tex-server 'texlab
+ "Choose LSP tex server."
+ :type '(choice (const :tag "texlab" texlab)
+ (const :tag "digestif" digestif))
+ :group 'lsp-tex)
+
+(defcustom lsp-clients-digestif-executable "digestif"
+ "Command to start the Digestif language server."
+ :group 'lsp-tex
+ :risky t
+ :type 'file)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-digestif-executable)
+ :major-modes '(plain-tex-mode latex-mode context-mode texinfo-mode)
+ :priority (if (eq lsp-tex-server 'digestif) 1 -1)
+ :server-id 'digestif))
+
+(defcustom lsp-clients-texlab-executable "texlab"
+ "Command to start the texlab language server."
+ :group 'lsp-tex
+ :risky t
+ :type 'file)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-texlab-executable)
+ :major-modes '(plain-tex-mode latex-mode)
+ :priority (if (eq lsp-tex-server 'texlab) 1 -1)
+ :server-id 'texlab))
+
+(lsp-consistency-check lsp-tex)
+
+(provide 'lsp-tex)
+;;; lsp-tex.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-v.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-v.el
new file mode 100644
index 0000000..a809a07
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-v.el
@@ -0,0 +1,50 @@
+;;; lsp-v.el --- lsp-mode V integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 remimimimi
+
+;; Author: remimimimi
+;; Keywords: languages,tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; client for vls, the V language server
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-v nil
+ "LSP support for V via vls."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/vlang/vls/tree/master"))
+
+(defcustom lsp-v-vls-executable "vls"
+ "The vls executable to use.
+Leave as just the executable name to use the default behavior of
+finding the executable with variable `exec-path'."
+ :group 'lsp-v
+ :type 'string)
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () lsp-v-vls-executable))
+ :activation-fn (lsp-activate-on "V")
+ :server-id 'v-ls))
+
+(lsp-consistency-check lsp-v)
+
+(provide 'lsp-v)
+;;; lsp-v.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vala.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vala.el
new file mode 100644
index 0000000..98f4e16
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vala.el
@@ -0,0 +1,51 @@
+;;; lsp-vala.el --- Vala Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Daniel Svensson
+
+;; Author: Daniel Svensson
+;; Keywords: vala lsp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP client for Vala
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-vala nil
+ "LSP support for Vala, using vala-language-server"
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/benwaffle/vala-language-server")
+ :package-version `(lsp-mode . "7.1.0"))
+
+(defcustom lsp-clients-vala-ls-executable "vala-language-server"
+ "Path to the `vala-language-server' binary."
+ :group 'lsp-vala
+ :risky t
+ :type 'file
+ :package-version `(lsp-mode . "7.1.0"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-clients-vala-ls-executable))
+ :major-modes '(vala-mode)
+ :priority -1
+ :server-id 'valals))
+
+(lsp-consistency-check lsp-vala)
+
+(provide 'lsp-vala)
+;;; lsp-vala.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-verilog.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-verilog.el
new file mode 100644
index 0000000..56df709
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-verilog.el
@@ -0,0 +1,186 @@
+;;; lsp-verilog.el --- Verilog Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Patrick Grogan
+
+;; Author: Patrick Grogan <pogrogan@gmail.com>
+;; Created: 7 December 2019
+;; Keywords: languages, lsp, verilog
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; LSP client support for Verilog/SystemVerilog. Two language servers
+;; are available:
+;; 1) HDL Checker. See https://github.com/suoto/hdl_checker
+;; 2) SVLangserver. See https://github.com/imc-trading/svlangserver
+;;
+;; This file is based on the lsp-vhdl.el file.
+;;
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-svlangserver nil
+ "Settings for the SystemVerilog language server client."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/imc-trading/svlangserver")
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-clients-svlangserver-includeIndexing '["**/*.{sv,svh}"]
+ "Files included for indexing (glob pattern)"
+ :group 'lsp-svlangserver
+ :type '(lsp-repeatable-vector string)
+ :safe (lambda (x) (seq-every-p #'stringp x)))
+
+(defcustom lsp-clients-svlangserver-excludeIndexing '["test/**/*.{sv,svh}"]
+ "Files excluded for indexing (glob pattern)"
+ :group 'lsp-svlangserver
+ :type '(lsp-repeatable-vector string)
+ :safe (lambda (x) (seq-every-p #'stringp x)))
+
+(defcustom lsp-clients-svlangserver-defines nil
+ "Defines needed for linting"
+ :group 'lsp-svlangserver
+ :type '(lsp-repeatable-vector string)
+ :safe (lambda (x) (seq-every-p #'stringp x)))
+
+(defcustom lsp-clients-svlangserver-launchConfiguration "verilator -sv --lint-only -Wall"
+ "Verilator command used for linting"
+ :group 'lsp-svlangserver
+ :type 'string
+ :safe (lambda (x) (stringp x)))
+
+(defcustom lsp-clients-svlangserver-lintOnUnsaved t
+ "Enable linting on unsaved files"
+ :group 'lsp-svlangserver
+ :type 'boolean
+ :safe (lambda (x) (booleanp x)))
+
+(defcustom lsp-clients-svlangserver-formatCommand "verible-verilog-format"
+ "Verible verilog format command"
+ :group 'lsp-svlangserver
+ :type 'string
+ :safe (lambda (x) (stringp x)))
+
+(defcustom lsp-clients-svlangserver-disableCompletionProvider nil
+ "Disable auto completion provided by the language server"
+ :group 'lsp-svlangserver
+ :type 'boolean
+ :safe (lambda (x) (booleanp x)))
+
+(defcustom lsp-clients-svlangserver-disableHoverProvider nil
+ "Disable hover over help provided by the language server"
+ :group 'lsp-svlangserver
+ :type 'boolean
+ :safe (lambda (x) (booleanp x)))
+
+(defcustom lsp-clients-svlangserver-disableSignatureHelpProvider nil
+ "Disable signature help provided by the language server"
+ :group 'lsp-svlangserver
+ :type 'boolean
+ :safe (lambda (x) (booleanp x)))
+
+(defcustom lsp-clients-svlangserver-disableLinting nil
+ "Disable verilator linting"
+ :group 'lsp-svlangserver
+ :type 'boolean
+ :safe (lambda (x) (booleanp x)))
+
+(defcustom lsp-clients-svlangserver-workspace-additional-dirs nil
+ "Additional directories to be managed by this instance of svlangserver"
+ :group 'lsp-svlangserver
+ :type '(lsp-repeatable-vector string)
+ :safe (lambda (x) (seq-every-p #'stringp x)))
+
+(defcustom lsp-clients-svlangserver-bin-path "svlangserver"
+ "svlangserver binary path"
+ :group 'lsp-svlangserver
+ :type 'string
+ :safe (lambda (x) (stringp x)))
+
+(defcustom lsp-clients-svlangserver-bin-args nil
+ "command line arguments for svlangserver binary"
+ :group 'lsp-svlangserver
+ :type '(lsp-repeatable-vector string)
+ :safe (lambda (x) (seq-every-p #'stringp x)))
+
+(defcustom lsp-clients-svlangserver-node-command "node"
+ "node binary path"
+ :group 'lsp-svlangserver
+ :type 'string
+ :safe (lambda (x) (stringp x)))
+
+(defcustom lsp-clients-svlangserver-module-path "svlangserver.js"
+ "svlangserver module path"
+ :group 'lsp-svlangserver
+ :type 'string
+ :safe (lambda (x) (stringp x)))
+
+(lsp-dependency 'svlangserver
+ '(:system "svlangserver"))
+
+(defun lsp-clients-svlangserver-get-workspace-additional-dirs (_workspace)
+ lsp-clients-svlangserver-workspace-additional-dirs)
+
+(defun lsp-clients-svlangserver-command ()
+ (let ((svlangserver-bin-path (lsp-package-path 'svlangserver)))
+ (if svlangserver-bin-path
+ (cons svlangserver-bin-path lsp-clients-svlangserver-bin-args)
+ (if (file-exists-p lsp-clients-svlangserver-bin-path)
+ (cons lsp-clients-svlangserver-bin-path lsp-clients-svlangserver-bin-args)
+ (if (file-exists-p lsp-clients-svlangserver-module-path)
+ `(,lsp-clients-svlangserver-node-command ,lsp-clients-svlangserver-module-path ,"--stdio")
+ `(,"svlangserver"))))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection 'lsp-clients-svlangserver-command)
+ :major-modes '(verilog-mode)
+ :priority -1
+ :library-folders-fn 'lsp-clients-svlangserver-get-workspace-additional-dirs
+ :server-id 'svlangserver))
+
+(lsp-register-custom-settings '(("systemverilog.includeIndexing" lsp-clients-svlangserver-includeIndexing)
+ ("systemverilog.excludeIndexing" lsp-clients-svlangserver-excludeIndexing)
+ ("systemverilog.defines" lsp-clients-svlangserver-defines)
+ ("systemverilog.launchConfiguration" lsp-clients-svlangserver-launchConfiguration)
+ ("systemverilog.lintOnUnsaved" lsp-clients-svlangserver-lintOnUnsaved)
+ ("systemverilog.formatCommand" lsp-clients-svlangserver-formatCommand)
+ ("systemverilog.disableCompletionProvider" lsp-clients-svlangserver-disableCompletionProvider)
+ ("systemverilog.disableHoverProvider" lsp-clients-svlangserver-disableHoverProvider)
+ ("systemverilog.disableSignatureHelpProvider" lsp-clients-svlangserver-disableSignatureHelpProvider)
+ ("systemverilog.disableLinting" lsp-clients-svlangserver-disableLinting)))
+
+(defgroup lsp-verilog nil
+ "LSP support for Verilog/SystemVerilog."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/suoto/hdl_checker"))
+
+(defcustom lsp-clients-verilog-executable '("hdl_checker" "--lsp")
+ "Command to start the hdl_checker language server."
+ :group 'lsp-verilog
+ :risky t
+ :type 'file)
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-verilog-executable)
+ :major-modes '(verilog-mode)
+ :language-id "verilog"
+ :priority -2
+ :server-id 'lsp-verilog))
+
+(lsp-consistency-check lsp-verilog)
+
+(provide 'lsp-verilog)
+;;; lsp-verilog.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vetur.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vetur.el
new file mode 100644
index 0000000..f23c539
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vetur.el
@@ -0,0 +1,869 @@
+;;; lsp-vetur.el --- vls configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; VLS configuration
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'lsp-html)
+
+(defgroup lsp-vetur nil
+ "LSP support for Vue, using the Vue Language Server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/vuejs/vetur/tree/master/server")
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-use-workspace-dependencies nil
+ "Use dependencies from workspace. Currently only for
+TypeScript."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-completion-auto-import t
+ "Include completion for module export and auto import them"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-completion-use-scaffold-snippets t
+ "Enable/disable Vetur's built-in scaffolding snippets"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-completion-tag-casing "kebab"
+ "Casing conversion for tag completion"
+ :type '(choice
+ (const "initial")
+ (const "kebab"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-grammar-custom-blocks '((docs . "md") (i18n . "json"))
+ "Mapping from custom block tag name to language name. Used for
+ generating grammar to support syntax highlighting for custom
+ blocks."
+ :type 'alist
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-validation-template t
+ "Validate vue-html in <template> using eslint-plugin-vue"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-language-features-code-actions t
+ "Enable/disable code actions."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-vetur-validation-style t
+ "Validate css/scss/less/postcss in <style>"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-validation-script t
+ "Validate js/ts in <script>"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-enable t
+ "Enable/disable the Vetur document formatter."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-options-tab-size 2
+ "Number of spaces per indentation level. Inherited by all formatters."
+ :type 'number
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-options-use-tabs nil
+ "Use tabs for indentation. Inherited by all formatters."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-html "prettyhtml"
+ "Default formatter for <template> region"
+ :type '(choice
+ (const "none")
+ (const "prettyhtml")
+ (const "js-beautify-html")
+ (const "prettier"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-css "prettier"
+ "Default formatter for <style> region"
+ :type '(choice
+ (const "none")
+ (const "prettier"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-postcss "prettier"
+ "Default formatter for <style lang='postcss'> region"
+ :type '(choice
+ (const "none")
+ (const "prettier"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-scss "prettier"
+ "Default formatter for <style lang='scss'> region"
+ :type '(choice
+ (const "none")
+ (const "prettier"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-less "prettier"
+ "Default formatter for <style lang='less'> region"
+ :type '(choice
+ (const "none")
+ (const "prettier"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-stylus "stylus-supremacy"
+ "Default formatter for <style lang='stylus'> region"
+ :type '(choice
+ (const "none")
+ (const "stylus-supremacy"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-js "prettier"
+ "Default formatter for <script> region"
+ :type '(choice
+ (const "none")
+ (const "prettier")
+ (const "prettier-eslint")
+ (const "vscode-typescript"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-ts "prettier"
+ "Default formatter for <script> region"
+ :type '(choice
+ (const "none")
+ (const "prettier")
+ (const "vscode-typescript"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-default-formatter-options
+ '((js-beautify-html (wrap_attributes . "force-expand-multiline"))
+ (prettyhtml (printWidth . 100)
+ (singleQuote . :json-false)
+ (wrapAttributes . :json-false)
+ (sortAttributes . :json-false)))
+ "Options for all default formatters"
+ :type 'alist
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-style-initial-indent nil
+ "Whether to have initial indent for <style> region"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-format-script-initial-indent nil
+ "Whether to have initial indent for <script> region"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-trace-server "off"
+ "Traces the communication between VS Code and Vue Language Server."
+ :type '(choice
+ (const "off")
+ (const "messages")
+ (const "verbose"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-dev-vls-path ""
+ "The vls path for development"
+ :type 'string
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-vetur-dev-vls-port -1
+ "The vls port for development"
+ :type 'integer
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-vetur-dev-log-level "INFO"
+ "The vls log level for development"
+ :type '(choice
+ (const "INFO")
+ (const "DEBUG"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-vetur-experimental-template-interpolation-service nil
+ "Whether to have template interpolation service"
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.3"))
+
+(defcustom lsp-typescript-tsdk nil
+ "Specifies the folder path containing the tsserver and
+lib*.d.ts files to use."
+ :type '(repeat string)
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-disable-automatic-type-acquisition nil
+ "Disables automatic type acquisition. Automatic type
+acquisition fetches `@types` packages from npm to improve
+IntelliSense for external libraries."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-npm nil
+ "Specifies the path to the NPM executable used for Automatic
+Type Acquisition. Requires using TypeScript 2.3.4 or newer in the
+workspace."
+ :type '(repeat string)
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-check-npm-is-installed t
+ "Check if NPM is installed for Automatic Type Acquisition."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-references-code-lens-enabled nil
+ "Enable/disable references CodeLens in JavaScript files."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-references-code-lens-enabled nil
+ "Enable/disable references CodeLens in TypeScript files."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-implementations-code-lens-enabled nil
+ "Enable/disable implementations CodeLens. This CodeLens shows
+the implementers of an interface."
+ :type 'boolean
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-tsserver-log "off"
+ "Enables logging of the TS server to a file. This log can be
+used to diagnose TS Server issues. The log may contain file
+paths, source code, and other potentially sensitive information
+from your project."
+ :type '(choice
+ (const "off")
+ (const "terse")
+ (const "normal")
+ (const "verbose"))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-tsserver-plugin-paths nil
+ "Additional paths to discover Typescript Language Service
+plugins. Requires using TypeScript 2.3.0 or newer in the
+workspace."
+ :type '(repeat string)
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-tsserver-trace "off"
+ "Enables tracing of messages sent to the TS server. This trace
+can be used to diagnose TS Server issues. The trace may contain
+file paths, source code, and other potentially sensitive
+information from your project."
+ :type '(choice
+ (const "off")
+ (const "messages")
+ (const "verbose"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-complete-function-calls nil
+ "Complete functions with their parameter signature."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggest-complete-function-calls nil
+ "Complete functions with their parameter signature."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-report-style-checks-as-warnings t
+ "Report style checks as warnings."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-validate-enable t
+ "Enable/disable TypeScript validation."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-enable t
+ "Enable/disable default TypeScript formatter."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-comma-delimiter t
+ "Defines space handling after a comma delimiter."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-constructor nil
+ "Defines space handling after the constructor keyword. Requires
+using TypeScript 2.3.0 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-semicolon-in-for-statements t
+ "Defines space handling after a semicolon in a for statement."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-before-and-after-binary-operators t
+ "Defines space handling after a binary operator."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-keywords-in-control-flow-statements t
+ "Defines space handling after keywords in a control flow
+statement."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-function-keyword-for-anonymous-functions t
+ "Defines space handling after function keyword for anonymous
+functions."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-before-function-parenthesis nil
+ "Defines space handling before function argument parentheses."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-parenthesis nil
+ "Defines space handling after opening and before closing
+non-empty parenthesis."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-brackets nil
+ "Defines space handling after opening and before closing
+non-empty brackets."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-braces t
+ "Defines space handling after opening and before closing
+non-empty braces. Requires using TypeScript 2.3.0 or newer in the
+workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-opening-and-before-closing-template-string-braces nil
+ "Defines space handling after opening and before closing
+template string braces."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-opening-and-before-closing-jsx-expression-braces nil
+ "Defines space handling after opening and before closing JSX
+expression braces."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-insert-space-after-type-assertion nil
+ "Defines space handling after type assertions in TypeScript.
+Requires using TypeScript 2.4 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-place-open-brace-on-new-line-for-functions nil
+ "Defines whether an open brace is put onto a new line for
+functions or not."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-format-place-open-brace-on-new-line-for-control-blocks nil
+ "Defines whether an open brace is put onto a new line for
+control blocks or not."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-validate-enable t
+ "Enable/disable JavaScript validation."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-enable t
+ "Enable/disable default JavaScript formatter."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-comma-delimiter t
+ "Defines space handling after a comma delimiter."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-constructor nil
+ "Defines space handling after the constructor keyword. Requires
+using TypeScript 2.3.0 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-semicolon-in-for-statements t
+ "Defines space handling after a semicolon in a for statement."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-before-and-after-binary-operators t
+ "Defines space handling after a binary operator."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-keywords-in-control-flow-statements t
+ "Defines space handling after keywords in a control flow
+statement."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-function-keyword-for-anonymous-functions t
+ "Defines space handling after function keyword for anonymous
+functions."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-before-function-parenthesis nil
+ "Defines space handling before function argument parentheses."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-parenthesis nil
+ "Defines space handling after opening and before closing
+non-empty parenthesis."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-brackets nil
+ "Defines space handling after opening and before closing
+non-empty brackets."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-braces t
+ "Defines space handling after opening and before closing
+non-empty braces. Requires using TypeScript 2.3.0 or newer in the
+workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-opening-and-before-closing-template-string-braces nil
+ "Defines space handling after opening and before closing
+template string braces."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-insert-space-after-opening-and-before-closing-jsx-expression-braces nil
+ "Defines space handling after opening and before closing JSX
+expression braces."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-place-open-brace-on-new-line-for-functions nil
+ "Defines whether an open brace is put onto a new line for
+functions or not."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-format-place-open-brace-on-new-line-for-control-blocks nil
+ "Defines whether an open brace is put onto a new line for
+control blocks or not."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-implicit-project-config-check-js nil
+ "Enable/disable semantic checking of JavaScript files. Existing
+jsconfig.json or tsconfig.json files override this setting.
+Requires using TypeScript 2.3.1 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-implicit-project-config-experimental-decorators nil
+ nil
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-names t
+ "Enable/disable including unique names from the file in
+JavaScript suggestions."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-tsc-auto-detect "on"
+ "Controls auto detection of tsc tasks."
+ :type '(choice
+ (const "on")
+ (const "off")
+ (const "build")
+ (const "watch"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-paths t
+ "Enable/disable suggestions for paths in import statements and
+require calls."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggest-paths t
+ "Enable/disable suggestions for paths in import statements and
+require calls."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-auto-imports t
+ "Enable/disable auto import suggestions. Requires using
+TypeScript 2.6.1 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggest-auto-imports t
+ "Enable/disable auto import suggestions. Requires using
+TypeScript 2.6.1 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-complete-js-docs t
+ "Enable/disable suggestion to complete JSDoc comments."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggest-complete-js-docs t
+ "Enable/disable suggestion to complete JSDoc comments."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-locale nil
+ nil
+ :type '(choice
+ (const "de")
+ (const "es")
+ (const "en")
+ (const "fr")
+ (const "it")
+ (const "ja")
+ (const "ko")
+ (const "ru")
+ (const "zh-CN")
+ (const "zh-TW")
+ nil)
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggestion-actions-enabled t
+ "Enable/disable suggestion diagnostics for JavaScript files in
+the editor. Requires using TypeScript 2.8 or newer in the
+workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggestion-actions-enabled t
+ "Enable/disable suggestion diagnostics for TypeScript files in
+the editor. Requires using TypeScript 2.8 or newer in the
+workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-preferences-quote-style "auto" nil
+ :type '(choice
+ (const "auto")
+ (const "single")
+ (const "double"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-preferences-quote-style "auto" nil
+ :type '(choice
+ (const "auto")
+ (const "single")
+ (const "double"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-preferences-import-module-specifier "auto"
+ "Preferred path style for auto imports."
+ :type '(choice
+ (const "auto")
+ (const "relative")
+ (const "non-relative"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-preferences-import-module-specifier "auto"
+ "Infer the shortest path type."
+ :type '(choice
+ (const "auto")
+ (const "relative")
+ (const "non-relative"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-preferences-rename-shorthand-properties t
+ "Enable/disable introducing aliases for object shorthand
+properties during renames. Requires using TypeScript 3.4 or newer
+in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-preferences-rename-shorthand-properties t
+ "Enable/disable introducing aliases for object shorthand
+properties during renames. Requires using TypeScript 3.4 or newer
+in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-update-imports-on-file-move-enabled "prompt"
+ "Enable/disable automatic updating of import paths when you
+rename or move a file in VS Code. Requires using TypeScript 2.9
+or newer in the workspace."
+ :type '(choice
+ (const "prompt")
+ (const "always")
+ (const "never"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-update-imports-on-file-move-enabled "prompt"
+ "Prompt on each rename."
+ :type '(choice
+ (const "prompt")
+ (const "always")
+ (const "never"))
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-auto-closing-tags t
+ "Enable/disable automatic closing of JSX tags. Requires using
+TypeScript 3.0 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-auto-closing-tags t
+ "Enable/disable automatic closing of JSX tags. Requires using
+TypeScript 3.0 or newer in the workspace."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-javascript-suggest-enabled t
+ "Enabled/disable autocomplete suggestions."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-suggest-enabled t
+ "Enabled/disable autocomplete suggestions."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-typescript-surveys-enabled t
+ "Enabled/disable occasional surveys that help us improve VS
+Code's JavaScript and TypeScript support."
+ :type 'boolean
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-vetur-emmet "never"
+ "Controls the Emmet suggestions that show up in the suggestion/completion list."
+ :type '(choice
+ (const "never")
+ (const "inMarkupAndStylesheetFilesOnly")
+ (const "always" ))
+ :group 'lsp-vetur
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-register-custom-settings
+ '(("javascript.autoClosingTags" lsp-javascript-auto-closing-tags t)
+ ("javascript.format.enable" lsp-javascript-format-enable t)
+ ("javascript.format.insertSpaceAfterCommaDelimiter" lsp-javascript-format-insert-space-after-comma-delimiter t)
+ ("javascript.format.insertSpaceAfterConstructor" lsp-javascript-format-insert-space-after-constructor t)
+ ("javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions" lsp-javascript-format-insert-space-after-function-keyword-for-anonymous-functions t)
+ ("javascript.format.insertSpaceAfterKeywordsInControlFlowStatements" lsp-javascript-format-insert-space-after-keywords-in-control-flow-statements t)
+ ("javascript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces" lsp-javascript-format-insert-space-after-opening-and-before-closing-jsx-expression-braces t)
+ ("javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces" lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-braces t)
+ ("javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets" lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-brackets t)
+ ("javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis" lsp-javascript-format-insert-space-after-opening-and-before-closing-nonempty-parenthesis t)
+ ("javascript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces" lsp-javascript-format-insert-space-after-opening-and-before-closing-template-string-braces t)
+ ("javascript.format.insertSpaceAfterSemicolonInForStatements" lsp-javascript-format-insert-space-after-semicolon-in-for-statements t)
+ ("javascript.format.insertSpaceBeforeAndAfterBinaryOperators" lsp-javascript-format-insert-space-before-and-after-binary-operators t)
+ ("javascript.format.insertSpaceBeforeFunctionParenthesis" lsp-javascript-format-insert-space-before-function-parenthesis t)
+ ("javascript.format.placeOpenBraceOnNewLineForControlBlocks" lsp-javascript-format-place-open-brace-on-new-line-for-control-blocks t)
+ ("javascript.format.placeOpenBraceOnNewLineForFunctions" lsp-javascript-format-place-open-brace-on-new-line-for-functions t)
+ ("javascript.implicitProjectConfig.checkJs" lsp-javascript-implicit-project-config-check-js t)
+ ("javascript.implicitProjectConfig.experimentalDecorators" lsp-javascript-implicit-project-config-experimental-decorators t)
+ ("javascript.preferences.importModuleSpecifier" lsp-javascript-preferences-import-module-specifier)
+ ("javascript.preferences.quoteStyle" lsp-javascript-preferences-quote-style)
+ ("javascript.preferences.renameShorthandProperties" lsp-javascript-preferences-rename-shorthand-properties t)
+ ("javascript.referencesCodeLens.enabled" lsp-javascript-references-code-lens-enabled t)
+ ("javascript.suggest.autoImports" lsp-javascript-suggest-auto-imports t)
+ ("javascript.suggest.completeFunctionCalls" lsp-javascript-suggest-complete-function-calls t)
+ ("javascript.suggest.completeJSDocs" lsp-javascript-suggest-complete-js-docs t)
+ ("javascript.suggest.enabled" lsp-javascript-suggest-enabled t)
+ ("javascript.suggest.names" lsp-javascript-suggest-names t)
+ ("javascript.suggest.paths" lsp-javascript-suggest-paths t)
+ ("javascript.suggestionActions.enabled" lsp-javascript-suggestion-actions-enabled t)
+ ("javascript.updateImportsOnFileMove.enabled" lsp-javascript-update-imports-on-file-move-enabled)
+ ("javascript.validate.enable" lsp-javascript-validate-enable t)
+ ("typescript.autoClosingTags" lsp-typescript-auto-closing-tags t)
+ ("typescript.check.npmIsInstalled" lsp-typescript-check-npm-is-installed t)
+ ("typescript.disableAutomaticTypeAcquisition" lsp-typescript-disable-automatic-type-acquisition t)
+ ("typescript.format.enable" lsp-typescript-format-enable t)
+ ("typescript.format.insertSpaceAfterCommaDelimiter" lsp-typescript-format-insert-space-after-comma-delimiter t)
+ ("typescript.format.insertSpaceAfterConstructor" lsp-typescript-format-insert-space-after-constructor t)
+ ("typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions" lsp-typescript-format-insert-space-after-function-keyword-for-anonymous-functions t)
+ ("typescript.format.insertSpaceAfterKeywordsInControlFlowStatements" lsp-typescript-format-insert-space-after-keywords-in-control-flow-statements t)
+ ("typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces" lsp-typescript-format-insert-space-after-opening-and-before-closing-jsx-expression-braces t)
+ ("typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces" lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-braces t)
+ ("typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets" lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-brackets t)
+ ("typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis" lsp-typescript-format-insert-space-after-opening-and-before-closing-nonempty-parenthesis t)
+ ("typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces" lsp-typescript-format-insert-space-after-opening-and-before-closing-template-string-braces t)
+ ("typescript.format.insertSpaceAfterSemicolonInForStatements" lsp-typescript-format-insert-space-after-semicolon-in-for-statements t)
+ ("typescript.format.insertSpaceAfterTypeAssertion" lsp-typescript-format-insert-space-after-type-assertion t)
+ ("typescript.format.insertSpaceBeforeAndAfterBinaryOperators" lsp-typescript-format-insert-space-before-and-after-binary-operators t)
+ ("typescript.format.insertSpaceBeforeFunctionParenthesis" lsp-typescript-format-insert-space-before-function-parenthesis t)
+ ("typescript.format.placeOpenBraceOnNewLineForControlBlocks" lsp-typescript-format-place-open-brace-on-new-line-for-control-blocks t)
+ ("typescript.format.placeOpenBraceOnNewLineForFunctions" lsp-typescript-format-place-open-brace-on-new-line-for-functions t)
+ ("typescript.implementationsCodeLens.enabled" lsp-typescript-implementations-code-lens-enabled t)
+ ("typescript.locale" lsp-typescript-locale)
+ ("typescript.npm" lsp-typescript-npm)
+ ("typescript.preferences.importModuleSpecifier" lsp-typescript-preferences-import-module-specifier)
+ ("typescript.preferences.quoteStyle" lsp-typescript-preferences-quote-style)
+ ("typescript.preferences.renameShorthandProperties" lsp-typescript-preferences-rename-shorthand-properties t)
+ ("typescript.referencesCodeLens.enabled" lsp-typescript-references-code-lens-enabled t)
+ ("typescript.reportStyleChecksAsWarnings" lsp-typescript-report-style-checks-as-warnings t)
+ ("typescript.suggest.autoImports" lsp-typescript-suggest-auto-imports t)
+ ("typescript.suggest.completeFunctionCalls" lsp-typescript-suggest-complete-function-calls t)
+ ("typescript.suggest.completeJSDocs" lsp-typescript-suggest-complete-js-docs t)
+ ("typescript.suggest.enabled" lsp-typescript-suggest-enabled t)
+ ("typescript.suggest.paths" lsp-typescript-suggest-paths t)
+ ("typescript.suggestionActions.enabled" lsp-typescript-suggestion-actions-enabled t)
+ ("typescript.surveys.enabled" lsp-typescript-surveys-enabled t)
+ ("typescript.tsc.autoDetect" lsp-typescript-tsc-auto-detect)
+ ("typescript.tsdk" lsp-typescript-tsdk)
+ ("typescript.tsserver.log" lsp-typescript-tsserver-log)
+ ("typescript.tsserver.pluginPaths" lsp-typescript-tsserver-plugin-paths)
+ ("typescript.tsserver.trace" lsp-typescript-tsserver-trace)
+ ("typescript.updateImportsOnFileMove.enabled" lsp-typescript-update-imports-on-file-move-enabled)
+ ("typescript.validate.enable" lsp-typescript-validate-enable t)
+ ("vetur.trace.server" lsp-vetur-trace-server)
+ ("vetur.format.scriptInitialIndent" lsp-vetur-format-script-initial-indent t)
+ ("vetur.format.styleInitialIndent" lsp-vetur-format-style-initial-indent t)
+ ("vetur.format.defaultFormatterOptions" lsp-vetur-format-default-formatter-options)
+ ("vetur.format.defaultFormatter.ts" lsp-vetur-format-default-formatter-ts)
+ ("vetur.format.defaultFormatter.js" lsp-vetur-format-default-formatter-js)
+ ("vetur.format.defaultFormatter.stylus" lsp-vetur-format-default-formatter-stylus)
+ ("vetur.format.defaultFormatter.less" lsp-vetur-format-default-formatter-less)
+ ("vetur.format.defaultFormatter.scss" lsp-vetur-format-default-formatter-scss)
+ ("vetur.format.defaultFormatter.postcss" lsp-vetur-format-default-formatter-postcss)
+ ("vetur.format.defaultFormatter.css" lsp-vetur-format-default-formatter-css)
+ ("vetur.format.defaultFormatter.html" lsp-vetur-format-default-formatter-html)
+ ("vetur.format.options.useTabs" lsp-vetur-format-options-use-tabs t)
+ ("vetur.format.options.tabSize" lsp-vetur-format-options-tab-size)
+ ("vetur.format.enable" lsp-vetur-format-enable t)
+ ("vetur.validation.script" lsp-vetur-validation-script t)
+ ("vetur.validation.style" lsp-vetur-validation-style t)
+ ("vetur.validation.template" lsp-vetur-validation-template t)
+ ("vetur.languageFeatures.codeActions" lsp-vetur-language-features-code-actions t)
+ ("vetur.grammar.customBlocks" lsp-vetur-grammar-custom-blocks)
+ ("vetur.completion.tagCasing" lsp-vetur-completion-tag-casing)
+ ("vetur.completion.useScaffoldSnippets" lsp-vetur-completion-use-scaffold-snippets t)
+ ("vetur.completion.autoImport" lsp-vetur-completion-auto-import t)
+ ("vetur.useWorkspaceDependencies" lsp-vetur-use-workspace-dependencies t)
+ ("vetur.dev.vlsPath" lsp-vetur-dev-vls-path)
+ ("vetur.dev.vlsPort" lsp-vetur-dev-vls-port)
+ ("vetur.dev.logLevel" lsp-vetur-dev-log-level)
+ ("vetur.experimental.templateInterpolationService" lsp-vetur-experimental-template-interpolation-service t)
+ ("emmet.showExpandedAbbreviation" lsp-vetur-emmet)))
+
+(define-obsolete-variable-alias
+ 'lsp-vetur-server
+ 'lsp-vetur-server-command
+ "lsp-mode 6.1")
+
+(defcustom lsp-vetur-global-snippets-dir (expand-file-name (locate-user-emacs-file ".snippets/vetur"))
+ "Path to snippets dir."
+ :type 'file
+ :risky t
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-vetur-server-command '("vls")
+ "Command to start vetur."
+ :type '(repeat string)
+ :risky t
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-dependency 'vetur-language-server
+ '(:system "vls")
+ '(:npm :package "vls" :path "vls"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find (cl-first lsp-vetur-server-command))
+ (lsp-package-path 'vetur-language-server))
+ ,@(cl-rest lsp-vetur-server-command))))
+ :activation-fn (lambda (filename _mode)
+ (string= (file-name-extension filename) "vue"))
+ :priority -1
+ :multi-root t
+ :ignore-messages '("readFile .*? requested by Vue but content not available")
+ :server-id 'vls
+ :initialization-options (lambda () (ht-merge (lsp-configuration-section "vetur")
+ (lsp-configuration-section "html")
+ (lsp-configuration-section "javascript")
+ (lsp-configuration-section "typescript")
+ (lsp-configuration-section "emmet")
+ (ht ("globalSnippetDir" lsp-vetur-global-snippets-dir))))
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (ht-merge (lsp-configuration-section "vetur")
+ (lsp-configuration-section "html")
+ (lsp-configuration-section "javascript")
+ (lsp-configuration-section "emmet")
+ (lsp-configuration-section "typescript")))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'vetur-language-server
+ callback error-callback))))
+
+(lsp-consistency-check lsp-vetur)
+
+(provide 'lsp-vetur)
+;;; lsp-vetur.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vhdl.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vhdl.el
new file mode 100644
index 0000000..aa55e0e
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vhdl.el
@@ -0,0 +1,121 @@
+;;; lsp-vhdl.el --- VHDL Client settings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Christian Birk Sørensen
+
+;; Author: Christian Birk Sørensen <chrbirks+emacs@gmail.com>
+;; Created: 6 October 2019
+;; Keywords: languages, lsp, vhdl
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP support for VHDL using using an external language server. Currently
+;; the supported servers are:
+;;
+;; VHDL-tool. See http://www.vhdltool.com/configuration for setting up the
+;; project file.
+;;
+;; HDL Checker. See https://github.com/suoto/hdl_checker/wiki/setting-up-a-project
+;; for setting up the project file.
+;;
+;; VHDL LS. See https://github.com/kraigher/rust_hdl#configuration for setting
+;; up the project file.
+;;
+;; GHDL LS. See https://github.com/ghdl/ghdl-language-server for setting up the
+;; project file.
+;;
+;; Set the symbol lsp-vhdl-server to select the language server and set
+;; lsp-vhdl-server-path if the binary is not in the user PATH.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defvar vhdl-tool-bin-name "vhdl-tool"
+ "Name of the VHDL Tool binary.")
+
+(defvar hdl-checker-bin-name "hdl_checker"
+ "Name of HDL Checker binary.")
+
+(defvar vhdl-ls-bin-name "vhdl_ls"
+ "Name of the VHDL LS binary.")
+
+(defvar ghdl-ls-bin-name "ghdl-ls"
+ "Name of the GHDL LS binary.")
+
+(defgroup lsp-vhdl nil
+ "LSP support for VHDL. Set lsp-vhdl-server to select server. The default is to use VHDL-tool."
+ :group 'lsp-mode)
+
+(defcustom lsp-vhdl-server 'vhdl-tool
+ "Select which server to use:
+VHDL-tool: A syntax checking, type checking and linting tool (http://vhdltool.com).
+HDL Checker: A wrapper for third party tools such as GHDL, ModelSim, Vivado Simulator (https://github.com/suoto/hdl_checker).
+VHDL LS: A complete VHDL language server protocol implementation with diagnostics, navigate to symbol, find all references etc. (https://github.com/kraigher/rust_hdl)."
+ :type '(choice (const :tag "VHDL-tool" vhdl-tool)
+ (const :tag "HDL Checker" hdl-checker)
+ (const :tag "VHDL LS" vhdl-ls)
+ (const :tag "GHDL LS" ghdl-ls))
+ :group 'lsp-vhdl)
+
+(defcustom lsp-vhdl-server-path nil
+ "Path to binary server file."
+ :group 'lsp-vhdl
+ :risky t
+ :type 'file)
+
+(defvar lsp-vhdl--params nil)
+
+(defun lsp-vhdl--create-connection ()
+ "Returns lsp-stdio-connection based on the selected server"
+ (lsp-vhdl--set-server-path)
+ (lsp-vhdl--set-server-args)
+ (lsp-stdio-connection
+ (lambda () (cons (plist-get lsp-vhdl--params 'server-path) (plist-get lsp-vhdl--params 'server-args)))
+ (lambda () (executable-find (plist-get lsp-vhdl--params 'server-path)))))
+
+(defun lsp-vhdl--set-server-path()
+ "Set path to server binary based on selection in lsp-vhdl-server."
+ (cond ((eq lsp-vhdl-server 'hdl-checker) (if (eq lsp-vhdl-server-path nil)
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path hdl-checker-bin-name))
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path lsp-vhdl-server-path))))
+ ((eq lsp-vhdl-server 'vhdl-tool) (if (eq lsp-vhdl-server-path nil)
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path vhdl-tool-bin-name))
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path lsp-vhdl-server-path))))
+ ((eq lsp-vhdl-server 'vhdl-ls) (if (eq lsp-vhdl-server-path nil)
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path vhdl-ls-bin-name))
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path lsp-vhdl-server-path))))
+ ((eq lsp-vhdl-server 'ghdl-ls) (if (eq lsp-vhdl-server-path nil)
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path ghdl-ls-bin-name))
+ (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-path lsp-vhdl-server-path))))))
+
+(defun lsp-vhdl--set-server-args()
+ "Set server arguments based on server selection."
+ (cond ((eq lsp-vhdl-server 'hdl-checker) (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-args '("--lsp"))))
+ ((eq lsp-vhdl-server 'vhdl-tool) (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-args '("lsp"))))
+ ((eq lsp-vhdl-server 'vhdl-ls) (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-args '())))
+ ((eq lsp-vhdl-server 'ghdl-ls) (setq lsp-vhdl--params (plist-put lsp-vhdl--params 'server-args '())))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-vhdl--create-connection)
+ :major-modes '(vhdl-mode)
+ :language-id "VHDL"
+ :priority -1
+ :server-id 'lsp-vhdl))
+
+(lsp-consistency-check lsp-vhdl)
+
+(provide 'lsp-vhdl)
+;;; lsp-vhdl.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vimscript.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vimscript.el
new file mode 100644
index 0000000..9f1fec2
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-vimscript.el
@@ -0,0 +1,75 @@
+;;; lsp-vimscript.el --- description -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 emacs-lsp maintainers
+
+;; Author: emacs-lsp maintainers
+;; Keywords: lsp, vim, vimscript
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; LSP Clients for the VimScript Programming Language.
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-vim nil
+ "LSP support for viml using vim-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/iamcco/vim-language-server"))
+
+(defcustom lsp-clients-vim-executable '("vim-language-server" "--stdio")
+ "Command to start the vim language server."
+ :group 'lsp-vim
+ :risky t
+ :type 'file)
+
+(defcustom lsp-clients-vim-initialization-options '((iskeyword . "vim iskeyword option")
+ (vimruntime . "/usr/bin/vim")
+ (runtimepath . "/usr/bin/vim")
+ (diagnostic . ((enable . t)))
+ (indexes . ((runtimepath . t)
+ (gap . 100)
+ (count . 3)))
+ (suggest . ((fromVimruntime . t)
+ (fromRuntimepath . :json-false))))
+ "Initialization options for vim language server."
+ :group 'lsp-vim
+ :type 'alist)
+
+(lsp-dependency 'vim-language-server
+ '(:system "vim-language-server")
+ '(:npm :package "vim-language-server"
+ :path "vim-language-server"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find (cl-first lsp-clients-vim-executable))
+ (lsp-package-path 'vim-language-server))
+ ,@(cl-rest lsp-clients-vim-executable))))
+ :major-modes '(vimrc-mode)
+ :priority -1
+ :server-id 'vimls
+ :initialization-options (lambda () lsp-clients-vim-initialization-options)
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'vim-language-server
+ callback error-callback))))
+
+(lsp-consistency-check lsp-vimscript)
+
+(provide 'lsp-vimscript)
+;;; lsp-vimscript.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-xml.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-xml.el
new file mode 100644
index 0000000..439f02f
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-xml.el
@@ -0,0 +1,245 @@
+;;; lsp-xml.el --- LSP XML server integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Ivan Yonchovski
+
+;; Author: Ivan Yonchovski <yyoncho@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-xml nil
+ "Settings for rls."
+ :group 'tools
+ :tag "Language Server"
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-trace-server "off"
+ "Traces the communication between VS Code and the XML language server."
+ :type '(choice
+ (const "off")
+ (const "messages")
+ (const "verbose"))
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-catalogs nil
+ "Array of XML Catalogs"
+ :type '(repeat string)
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-logs-client t
+ "Should the server log to client output"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-split-attributes nil
+ "Split multiple attributes each onto a new line"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-join-cdata-lines nil
+ "Join lines in a CDATA tag's content"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-join-comment-lines nil
+ "Join comment content on format"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-space-before-empty-close-tag t
+ "Insert space before end of self closing tag.
+Example: <tag/> -> <tag />"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-join-content-lines nil
+ "Normalize the whitespace of content inside an element.
+Newlines and excess whitespace are removed."
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-preserve-empty-content nil
+ "Preserve empty content/whitespace in a tag."
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-enabled t
+ "Enable/disable ability to format document"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-format-quotations "doubleQuotes"
+ "Which type of quotes to use for attribute values when
+ formatting."
+ :type '(choice
+ (const "doubleQuotes")
+ (const "singleQuotes"))
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-file-associations nil
+ "Allows XML schemas to be associated to file name patterns.
+ Example: [{ \"systemId\":\"path/to/file.xsd\",\"pattern\":
+ \"file1.xml\" },{ \"systemId\":
+ \"http://www.w3.org/2001/XMLSchema.xsd\",\"pattern\":
+ \"**/*.xsd\" }]"
+ :type '(repeat string)
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-completion-auto-close-tags t
+ "Enable/disable autoclosing of XML tags. IMPORTANT: Turn off
+ editor.autoClosingTags for this to work"
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-server-vmargs ["-noverify" "-Xmx64M" "-XX:+UseG1GC"
+ "-XX:+UseStringDeduplication"]
+ "Specifies extra VM arguments used to launch the XML Language
+ Server. Eg. use `-noverify -Xmx1G -XX:+UseG1GC
+ -XX:+UseStringDeduplication` to bypass class verification,
+ increase the heap size to 1GB and enable String deduplication
+ with the G1 Garbage collector"
+ :type 'lsp-string-vector
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-server-work-dir (expand-file-name ".lsp4xml" "~")
+ "Set a custom folder path for cached XML Schemas. An absolute
+ path is expected, although the ~ prefix (for the user home
+ directory) is supported."
+ :type 'string
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-validation-no-grammar "hint"
+ "The message severity when a document has no associated
+ grammar."
+ :type '(choice (:tag "ignore" "hint" "info" "warning" "error"))
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-validation-enabled t
+ "Enable/disable all validation."
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-validation-resolve-external-entities nil
+ "Enable/disable resolution (downloading) of external entities from the internet."
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "7.1"))
+
+(defcustom lsp-xml-validation-schema t
+ "Enable/disable schema based validation. Ignored if
+ \"xml.validation.enabled\": false."
+ :type 'boolean
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(lsp-register-custom-settings '
+ (("xml.validation.schema" lsp-xml-validation-schema t)
+ ("xml.validation.resolveExternalEntities" lsp-xml-validation-resolve-external-entities)
+ ("xml.validation.enabled" lsp-xml-validation-enabled t)
+ ("xml.validation.noGrammar" lsp-xml-validation-no-grammar)
+ ("xml.server.workDir" lsp-xml-server-work-dir)
+ ("xml.server.vmargs" lsp-xml-server-vmargs)
+ ("xml.completion.autoCloseTags" lsp-xml-completion-auto-close-tags t)
+ ("xml.fileAssociations" lsp-xml-file-associations)
+ ("xml.format.quotations" lsp-xml-format-quotations)
+ ("xml.format.enabled" lsp-xml-format-enabled t)
+ ("xml.format.preserveEmptyContent" lsp-xml-format-preserve-empty-content t)
+ ("xml.format.joinContentLines" lsp-xml-format-join-content-lines t)
+ ("xml.format.spaceBeforeEmptyCloseTag" lsp-xml-format-space-before-empty-close-tag t)
+ ("xml.format.joinCommentLines" lsp-xml-format-join-comment-lines t)
+ ("xml.format.joinCDATALines" lsp-xml-format-join-cdata-lines t)
+ ("xml.format.splitAttributes" lsp-xml-format-split-attributes t)
+ ("xml.logs.client" lsp-xml-logs-client t)
+ ("xml.catalogs" lsp-xml-catalogs)
+ ("xml.trace.server" lsp-xml-trace-server)))
+
+(defconst lsp-xml-jar-version "0.13.1")
+
+(defconst lsp-xml-jar-name (format "org.eclipse.lemminx-%s-uber.jar" lsp-xml-jar-version))
+
+(defcustom lsp-xml-jar-file (f-join lsp-server-install-dir "xmlls" lsp-xml-jar-name)
+ "Xml server jar command."
+ :type 'string
+ :group 'lsp-xml
+ :type 'file
+ :package-version '(lsp-mode . "6.1"))
+
+(defcustom lsp-xml-jar-download-url
+ (format
+ "https://repo.eclipse.org/content/repositories/lemminx-releases/org/eclipse/lemminx/org.eclipse.lemminx/%s/%s"
+ lsp-xml-jar-version
+ lsp-xml-jar-name)
+ "Automatic download url for lsp-xml."
+ :type 'string
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "7.1"))
+
+(lsp-dependency
+ 'xmlls
+ '(:system lsp-xml-jar-file)
+ `(:download :url lsp-xml-jar-download-url
+ :store-path lsp-xml-jar-file))
+
+(defcustom lsp-xml-server-command `("java" "-jar" ,lsp-xml-jar-file)
+ "Xml server command."
+ :type '(repeat string)
+ :group 'lsp-xml
+ :package-version '(lsp-mode . "6.1"))
+
+(defun lsp-xml--create-connection ()
+ (lsp-stdio-connection
+ (lambda () lsp-xml-server-command)
+ (lambda () (f-exists? lsp-xml-jar-file))))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-xml--create-connection)
+ :activation-fn (lsp-activate-on "xml")
+ :priority 0
+ :server-id 'xmlls
+ :multi-root t
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration (lsp-configuration-section "xml"))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'xmlls callback error-callback))))
+
+(lsp-consistency-check lsp-xml)
+
+(provide 'lsp-xml)
+;;; lsp-xml.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-yaml.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-yaml.el
new file mode 100644
index 0000000..bc7795e
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-yaml.el
@@ -0,0 +1,242 @@
+;;; lsp-yaml.el --- LSP YAML server integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Aya Igarashi
+
+;; Author: Aya Igarashi <ladiclexxx@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'dash)
+
+(defgroup lsp-yaml nil
+ "LSP support for YAML, using yaml-language-server."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/redhat-developer/yaml-language-server")
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-format-enable t
+ "Enable/disable default YAML formatter."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-single-quote nil
+ "Use single quote instead of double quotes."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-bracket-spacing t
+ "Print spaces between brackets in objects."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-prose-wrap "preserve"
+ "Options for prose-wrap.
+ Always: wrap prose if it exceeds the print width.
+ Never: never wrap the prose.
+ Preserve: wrap prose as-is."
+ :type '(choice
+ (const "always")
+ (const "never")
+ (const "preserve"))
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-print-width 80
+ "Specify the line length that the printer will wrap on."
+ :type 'number
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-validate t
+ "Enable/disable validation feature."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-hover t
+ "Enable/disable hover feature."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-completion t
+ "Enable/disable completion feature."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-schemas '()
+ "Associate schemas to YAML files in a glob pattern."
+ :type '(alist :key-type (symbol :tag "schema") :value-type (lsp-string-vector :tag "files (glob)"))
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-schema-store-enable t
+ "Enable/disable JSON Schema store. When set to true, available YAML
+ schemas will be automatically pulled from the store."
+ :type 'boolean
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-custom-tags nil
+ "Custom tags for the parser to use."
+ :type '(lsp-repeatable-vector string)
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(defcustom lsp-yaml-schema-store-uri "https://www.schemastore.org/api/json/catalog.json"
+ "URL of schema store catalog to use."
+ :type 'string
+ :group 'lsp-yaml)
+
+(defcustom lsp-yaml-schema-store-local-db (expand-file-name
+ (locate-user-emacs-file
+ (f-join ".cache" "lsp" "lsp-yaml-schemas.json")))
+ "Cached databse of schema store."
+ :type 'file
+ :group 'lsp-yaml)
+
+(defcustom lsp-yaml-max-items-computed 5000
+ "The maximum number of outline symbols and folding regions computed.
+Limited for performance reasons."
+ :type 'number
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "7.1"))
+
+
+(defvar lsp-yaml--schema-store-schemas-alist nil
+ "A list of schemas fetched from schema stores.")
+
+(lsp-register-custom-settings
+ '(("yaml.format.enable" lsp-yaml-format-enable t)
+ ("yaml.format.singleQuote" lsp-yaml-single-quote t)
+ ("yaml.format.bracketSpacing" lsp-yaml-bracket-spacing)
+ ("yaml.format.proseWrap" lsp-yaml-prose-wrap)
+ ("yaml.format.printWidth" lsp-yaml-print-width)
+ ("yaml.validate" lsp-yaml-validate t)
+ ("yaml.hover" lsp-yaml-hover t)
+ ("yaml.completion" lsp-yaml-completion t)
+ ("yaml.schemas" lsp-yaml-schemas)
+ ("yaml.schemaStore.enable" lsp-yaml-schema-store-enable t)
+ ("yaml.schemaStore.url" lsp-yaml-schema-store-uri)
+ ("yaml.customTags" lsp-yaml-custom-tags)
+ ("yaml.maxItemsComputed" lsp-yaml-max-items-computed)))
+
+(defcustom lsp-yaml-server-command '("yaml-language-server" "--stdio")
+ "Command to start yaml-languageserver."
+ :type '(repeat string)
+ :group 'lsp-yaml
+ :package-version '(lsp-mode . "6.2"))
+
+(lsp-dependency 'yaml-language-server
+ '(:system "yaml-language-server")
+ '(:npm :package "yaml-language-server"
+ :path "yaml-language-server"))
+
+(lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection
+ (lambda ()
+ `(,(or (executable-find (cl-first lsp-yaml-server-command))
+ (lsp-package-path 'yaml-language-server))
+ ,@(cl-rest lsp-yaml-server-command))))
+ :major-modes '(yaml-mode k8s-mode)
+ :priority 0
+ :server-id 'yamlls
+ :initialized-fn (lambda (workspace)
+ (with-lsp-workspace workspace
+ (lsp--set-configuration
+ (lsp-configuration-section "yaml"))))
+ :download-server-fn (lambda (_client callback error-callback _update?)
+ (lsp-package-ensure 'yaml-language-server
+ callback error-callback))))
+
+(defconst lsp-yaml--built-in-kubernetes-schema
+ '((name . "Kubernetes")
+ (description . "Built-in kubernetes manifest schema definition")
+ (url . "kubernetes")
+ (fileMatch . ["*-k8s.yaml" "*-k8s.yml"])))
+
+(defun lsp-yaml-download-schema-store-db (&optional force-downloading)
+ "Download the remote schema store at `lsp-yaml-schema-store-uri' into local cache.
+Set FORCE-DOWNLOADING to non-nil to force re-download the database."
+ (interactive "P")
+ (when (or force-downloading (not (file-exists-p lsp-yaml-schema-store-local-db)))
+ (unless (file-directory-p (file-name-directory lsp-yaml-schema-store-local-db))
+ (mkdir (file-name-directory lsp-yaml-schema-store-local-db)))
+ (url-copy-file lsp-yaml-schema-store-uri lsp-yaml-schema-store-local-db force-downloading)))
+
+(defun lsp-yaml--get-supported-schemas ()
+ "Get out the list of supported schemas."
+ (when (and lsp-yaml-schema-store-enable
+ (not lsp-yaml--schema-store-schemas-alist))
+ (lsp-yaml-download-schema-store-db)
+ (setq lsp-yaml--schema-store-schemas-alist
+ (alist-get 'schemas (json-read-file lsp-yaml-schema-store-local-db))))
+ (seq-concatenate 'list (list lsp-yaml--built-in-kubernetes-schema) lsp-yaml--schema-store-schemas-alist))
+
+(defun lsp-yaml-set-buffer-schema (uri-string)
+ "Set yaml schema for the current buffer to URI-STRING."
+ (interactive "MURI: ")
+ (let* ((uri (intern uri-string))
+ (workspace-path (file-relative-name
+ (lsp--uri-to-path (lsp--buffer-uri))
+ (lsp-workspace-root (lsp--buffer-uri))))
+ (glob (concat "/" workspace-path))
+ (current-config (assoc uri lsp-yaml-schemas))
+ (current-patterns (and current-config (cdr current-config))))
+ (if current-config
+ (or (member glob (append current-patterns nil))
+ (setq lsp-yaml-schemas
+ (cl-acons uri
+ (vconcat (vector glob) current-patterns)
+ (assq-delete-all uri
+ (mapcar (lambda (x) (lsp-yaml--remove-glob x glob))
+ lsp-yaml-schemas)))))
+ (setq lsp-yaml-schemas
+ (cl-acons uri (vector glob) (mapcar (lambda (x) (lsp-yaml--remove-glob x glob))
+ lsp-yaml-schemas))))
+ (lsp--set-configuration (lsp-configuration-section "yaml"))))
+
+(defun lsp-yaml-select-buffer-schema ()
+ "Select schema for the current buffer based on the list of supported schemas."
+ (interactive)
+ (let* ((schema (lsp--completing-read "Select buffer schema: "
+ (lsp-yaml--get-supported-schemas)
+ (lambda (schema)
+ (format "%s: %s" (alist-get 'name schema)(alist-get 'description schema)))
+ nil t))
+ (uri (alist-get 'url schema)))
+ (lsp-yaml-set-buffer-schema uri)))
+
+(defun lsp-yaml--remove-glob (mapping glob)
+ (let ((patterns (cdr mapping)))
+ (cons (car mapping)
+ (vconcat (-filter (lambda (p) (not (equal p glob)))
+ (append patterns nil)) nil))))
+
+(lsp-consistency-check lsp-yaml)
+
+(provide 'lsp-yaml)
+;;; lsp-yaml.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp-zig.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-zig.el
new file mode 100644
index 0000000..0d19acd
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp-zig.el
@@ -0,0 +1,50 @@
+;;; lsp-zig.el --- lsp-mode Zig integration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Riccardo Binetti
+
+;; Author: Riccardo Binetti <rbino@gmx.com>
+;; Keywords: languages,tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; client for zls, the Zig language server
+
+;;; Code:
+
+(require 'lsp-mode)
+
+(defgroup lsp-zig nil
+ "LSP support for Zig via zls."
+ :group 'lsp-mode
+ :link '(url-link "https://github.com/zigtools/zls"))
+
+(defcustom lsp-zig-zls-executable "zls"
+ "The zls executable to use.
+Leave as just the executable name to use the default behavior of
+finding the executable with variable `exec-path'."
+ :group 'lsp-zig
+ :type 'string)
+
+(lsp-register-client
+ (make-lsp-client
+ :new-connection (lsp-stdio-connection (lambda () lsp-zig-zls-executable))
+ :activation-fn (lsp-activate-on "zig")
+ :server-id 'zls))
+
+(lsp-consistency-check lsp-zig)
+
+(provide 'lsp-zig)
+;;; lsp-zig.el ends here
diff --git a/emacs.d/elpa/lsp-mode-20210716.2233/lsp.el b/emacs.d/elpa/lsp-mode-20210716.2233/lsp.el
new file mode 100644
index 0000000..e4f4b5d
--- /dev/null
+++ b/emacs.d/elpa/lsp-mode-20210716.2233/lsp.el
@@ -0,0 +1,8 @@
+;; The code was moved into lsp-mode.el. This file is kept only for backward compatibility.
+(require 'lsp-mode)
+
+;; (warn "Replace (require 'lsp) with (require 'lsp-mode)")
+
+(provide 'lsp)
+
+;;; lsp.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-autoloads.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-autoloads.el
new file mode 100644
index 0000000..bf3c8cc
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-autoloads.el
@@ -0,0 +1,80 @@
+;;; lsp-ui-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "lsp-ui" "lsp-ui.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ui.el
+
+(autoload 'lsp-ui-mode "lsp-ui" "\
+Toggle language server UI mode on or off.
+‘lsp-ui-mode’ is a minor mode that contains a series of useful UI
+integrations for ‘lsp-mode’. With a prefix argument ARG, enable
+language server UI mode if ARG is positive, and disable it
+otherwise. If called from Lisp, enable the mode if ARG is
+omitted or nil, and toggle it if ARG is ‘toggle’.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui" '("lsp-ui-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-doc" "lsp-ui-doc.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ui-doc.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-doc" '("lsp-ui-doc-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-flycheck" "lsp-ui-flycheck.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from lsp-ui-flycheck.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-flycheck" '("lsp-ui-flycheck-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-imenu" "lsp-ui-imenu.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ui-imenu.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-imenu" '("lsp-ui-imenu")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-peek" "lsp-ui-peek.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ui-peek.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-peek" '("lsp-")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-sideline" "lsp-ui-sideline.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from lsp-ui-sideline.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-sideline" '("lsp-ui-sideline")))
+
+;;;***
+
+;;;### (autoloads nil "lsp-ui-util" "lsp-ui-util.el" (0 0 0 0))
+;;; Generated autoloads from lsp-ui-util.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lsp-ui-util" '("lsp-ui-util-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("lsp-ui-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; lsp-ui-autoloads.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.el
new file mode 100644
index 0000000..8ba7ce7
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.el
@@ -0,0 +1,1195 @@
+;;; lsp-ui-doc.el --- Lsp-Ui-Doc -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Sebastien Chapuis
+
+;; Author: Sebastien Chapuis <sebastien@chapu.is>
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languagues, tools
+;; Version: 6.2
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; Show documentation of the symbol at point in a child frame
+
+;;; Code:
+
+(require 'lsp-ui-util)
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+(require 'dash)
+(require 'goto-addr)
+(require 'markdown-mode)
+
+(require 'cl-lib)
+(require 'face-remap)
+(require 'subr-x)
+
+(when (featurep 'xwidget-internal)
+ (require 'xwidget))
+
+(declare-function make-xwidget "ext:xwidget" (type title width height arguments &optional buffer))
+(declare-function set-xwidget-query-on-exit-flag "ext:xwidget")
+(declare-function xwidget-webkit-mode "ext:xwidget")
+(declare-function xwidget-webkit-goto-uri "ext:xwidget" (xwidget uri))
+(declare-function xwidget-at "ext:xwidget" (pos))
+(declare-function xwidget-webkit-execute-script "ext:xwidget" (xwidget script &optional callback))
+(declare-function xwidget-webkit-execute-script-rv "ext:xwidget" (xwidget script &optional default))
+(declare-function xwidget-resize "ext:xwidget" (xwidget new-width new-height))
+
+(defgroup lsp-ui-doc nil
+ "Display informations of the current line."
+ :group 'tools
+ :group 'convenience
+ :group 'lsp-ui
+ :link '(custom-manual "(lsp-ui-doc) Top")
+ :link '(info-link "(lsp-ui-doc) Customizing"))
+
+(defcustom lsp-ui-doc-enable t
+ "Whether or not to enable lsp-ui-doc."
+ :type 'boolean
+ :group 'lsp-ui)
+
+(defcustom lsp-ui-doc-show-with-mouse t
+ "Move the mouse pointer over a symbol to show its documentation."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-show-with-cursor t
+ "Move the cursor over a symbol to show its documentation."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-header nil
+ "Whether or not to enable the header which display the symbol string."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-include-signature nil
+ "Whether or not to include the object signature/type in the frame."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-position 'top
+ "Where to display the doc when moving the point cursor.
+This affect the position of the documentation when `lsp-ui-doc-show-with-cursor'
+is non-nil."
+ :type '(choice (const :tag "Top" top)
+ (const :tag "Bottom" bottom)
+ (const :tag "At point" at-point))
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-alignment 'frame
+ "How to align the doc.
+This only takes effect when `lsp-ui-doc-position' is 'top or 'bottom."
+ :type '(choice (const :tag "Frame" frame)
+ (const :tag "Window" window))
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-border "white"
+ "Border color of the frame."
+ :type 'color
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-max-width 150
+ "Maximum number of columns of the frame."
+ :type 'integer
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-max-height 13
+ "Maximum number of lines in the frame."
+ :type 'integer
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-use-childframe t
+ "Whether to display documentation in a child-frame or the current frame.
+Child frames requires GNU/Emacs version >= 26 and graphical frames."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-use-webkit nil
+ "Whether to display documentation in a WebKit widget in a child-frame.
+This requires GNU/Emacs version >= 26 and built with the `--with-xwidgets`
+option."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-delay 0.2
+ "Number of seconds before showing the doc."
+ :type 'number
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-winum-ignore t
+ "Whether to ignore lsp-ui-doc buffers in winum."
+ :type 'boolean
+ :group 'lsp-ui-doc)
+
+(defcustom lsp-ui-doc-text-scale-level 0
+ "Text scale amount for doc buffer."
+ :type 'integer
+ :group 'lsp-ui-doc)
+
+(defface lsp-ui-doc-background
+ '((((background light)) :background "#b3b3b3")
+ (t :background "#272A36"))
+ "Background color of the documentation.
+Only the `background' is used in this face."
+ :group 'lsp-ui-doc)
+
+(defface lsp-ui-doc-header
+ '((t :foreground "black"
+ :background "deep sky blue"))
+ "Face used on the header."
+ :group 'lsp-ui-doc)
+
+(defface lsp-ui-doc-highlight-hover
+ '((t :inherit region))
+ "Face used to highlight the hover symbol/region when using mouse."
+ :group 'lsp-ui-doc)
+
+(defface lsp-ui-doc-url
+ '((t :inherit link))
+ "Face used on links."
+ :group 'lsp-ui-doc)
+
+(defvar lsp-ui-doc-frame-parameters
+ '((left . -1)
+ (no-focus-on-map . t)
+ (min-width . 0)
+ (width . 0)
+ (min-height . 0)
+ (height . 0)
+ (internal-border-width . 1)
+ (vertical-scroll-bars . nil)
+ (horizontal-scroll-bars . nil)
+ (right-fringe . 0)
+ (menu-bar-lines . 0)
+ (tool-bar-lines . 0)
+ (line-spacing . 0)
+ (unsplittable . t)
+ (undecorated . t)
+ (top . -1)
+ (visibility . nil)
+ (mouse-wheel-frame . nil)
+ (no-other-frame . t)
+ (inhibit-double-buffering . t)
+ (drag-internal-border . t)
+ (no-special-glyphs . t)
+ (desktop-dont-save . t))
+ "Frame parameters used to create the frame.")
+
+(defvar lsp-ui-doc-render-function nil
+ "Function called to format the documentation.
+The function takes a string as parameter and should return a string.
+If this variable is nil (the default), the documentation will be rendered
+as markdown.")
+
+(defvar lsp-ui-doc-frame-hook nil
+ "Hooks run on child-frame creation.
+The functions receive 2 parameters: the frame and its window.")
+
+(defvar lsp-ui-doc-webkit-client-path
+ (concat "file://"
+ (file-name-directory (or load-file-name buffer-file-name))
+ "lsp-ui-doc.html")
+ "Path to the page loaded when a WebKit widget is created.")
+
+;; Avoid warning with emacs < 26
+(declare-function display-buffer-in-child-frame "window.el")
+
+(defvar-local lsp-ui-doc--parent-vars nil
+ "Variables from the parents frame that we want to access in the child.
+Because some variables are buffer local.")
+
+(defvar-local lsp-ui-doc--inline-ov nil
+ "Overlay used to display the documentation in the buffer.")
+
+(defvar-local lsp-ui-doc--highlight-ov nil
+ "Overlay used to highlight the hover symbol.")
+
+(defvar-local lsp-ui-doc--bounds nil)
+(defvar-local lsp-ui-doc--timer nil)
+(defvar-local lsp-ui-doc--from-mouse nil
+ "Non nil when the doc was triggered by a mouse event.")
+(defvar-local lsp-ui-doc--from-mouse-current nil
+ "Non nil when the current call is triggered by a mouse event")
+
+(defconst lsp-ui-doc--buffer-prefix " *lsp-ui-doc-")
+
+(defmacro lsp-ui-doc--with-buffer (&rest body)
+ "Execute BODY in the lsp-ui-doc buffer."
+ (declare (indent 0) (debug t))
+ `(let ((parent-vars (list :buffer (current-buffer)
+ :window (get-buffer-window)))
+ (buffer-list-update-hook nil))
+ (with-current-buffer (get-buffer-create (lsp-ui-doc--make-buffer-name))
+ (setq lsp-ui-doc--parent-vars parent-vars)
+ (prog1 (let ((buffer-read-only nil)
+ (inhibit-modification-hooks t)
+ (inhibit-point-motion-hooks t)
+ (inhibit-redisplay t))
+ ,@body)
+ (setq buffer-read-only t)
+ (let ((text-scale-mode-step 1.1))
+ (text-scale-set lsp-ui-doc-text-scale-level))))))
+
+(defmacro lsp-ui-doc--get-parent (var)
+ "Return VAR in `lsp-ui-doc--parent-vars'."
+ `(plist-get lsp-ui-doc--parent-vars ,var))
+
+(defmacro lsp-ui-doc--set-frame (frame)
+ "Set the frame parameter ‘lsp-ui-doc-frame’ to FRAME."
+ `(set-frame-parameter nil 'lsp-ui-doc-frame ,frame))
+
+(defun lsp-ui-doc--get-frame (&optional _)
+ "Return the child frame."
+ (let ((frame (frame-parameter nil 'lsp-ui-doc-frame)))
+ (and (frame-live-p frame) frame)))
+
+(defsubst lsp-ui-doc--frame-visible-p ()
+ "Return child frame visibility."
+ (let ((frame (lsp-ui-doc--get-frame)))
+ (and frame (frame-visible-p frame))))
+
+(defun lsp-ui-doc--make-buffer-name ()
+ "Construct the buffer name, it should be unique for each frame."
+ (concat lsp-ui-doc--buffer-prefix
+ (or (frame-parameter nil 'window-id)
+ (frame-parameter nil 'name))
+ "*"))
+
+;; ‘markdown-fontify-code-block-default-mode’ isn’t yet available in
+;; Markdown 2.3.
+(defvar markdown-fontify-code-block-default-mode)
+
+(defun lsp-ui-doc--inline-wrapped-line (string)
+ "Wraps a line of text (STRING) for inline display."
+ (cond ((string-empty-p string) "")
+ (t string)))
+
+(defun lsp-ui-doc--inline-formatted-string (string)
+ "Formats STRING for inline rendering."
+ (mapconcat (lambda (line)
+ (lsp-ui-doc--inline-wrapped-line (string-trim-right line)))
+ (split-string string "[\n\v\f\r]")
+ "\n"))
+
+(defun lsp-ui-doc--extract-marked-string (marked-string &optional language)
+ "Render the MARKED-STRING with LANGUAGE."
+ (string-trim-right
+ (let* ((string (if (stringp marked-string)
+ marked-string
+ (lsp:markup-content-value marked-string)))
+ (with-lang (lsp-marked-string? marked-string))
+ (language (or (and with-lang
+ (or (lsp:marked-string-language marked-string)
+ (lsp:markup-content-kind marked-string)))
+ language))
+ (markdown-hr-display-char nil))
+ (cond
+ (lsp-ui-doc-use-webkit
+ (if (and language (not (string= "text" language)))
+ (format "```%s\n%s\n```" language string)
+ string))
+ ;; For other programming languages
+ (language (lsp--render-string (lsp-ui-doc--inline-formatted-string string) language))
+ ;; For default element content
+ (t (lsp--render-element (lsp-ui-doc--inline-formatted-string string)))))))
+
+(defun lsp-ui-doc--filter-marked-string (list-marked-string)
+ "Filter the LIST-MARKED-STRING."
+ (let ((groups (--separate (and (lsp-marked-string? it)
+ (lsp-get-renderer (lsp:marked-string-language it)))
+ (append list-marked-string nil))))
+ (if lsp-ui-doc-include-signature
+ list-marked-string
+ (cadr groups))))
+
+(defun lsp-ui-doc--extract (contents)
+ "Extract the documentation from CONTENTS.
+CONTENTS can be differents type of values:
+MarkedString | MarkedString[] | MarkupContent (as defined in the LSP).
+We don't extract the string that `lps-line' is already displaying."
+ (cond
+ ((vectorp contents) ;; MarkedString[]
+ (mapconcat 'lsp-ui-doc--extract-marked-string
+ (lsp-ui-doc--filter-marked-string (seq-filter #'identity contents))
+ "\n\n"
+ ;;(propertize "\n\n" 'face '(:height 0.4))
+ ))
+ ;; when we get markdown contents, render using emacs gfm-view-mode / markdown-mode
+ ((and (lsp-marked-string? contents)
+ (lsp:marked-string-language contents))
+ (lsp-ui-doc--extract-marked-string (lsp:marked-string-value contents)
+ (lsp:marked-string-language contents)))
+ ;; The specification for MarkedString also includes raw strings of
+ ;; markdown, which is not reflected by `lsp-marked-string?'
+ ((stringp contents)
+ (lsp-ui-doc--extract-marked-string contents lsp/markup-kind-markdown))
+ ((lsp-marked-string? contents) (lsp-ui-doc--extract-marked-string contents))
+ ((and (lsp-markup-content? contents)
+ (string= (lsp:markup-content-kind contents) lsp/markup-kind-markdown))
+ (lsp-ui-doc--extract-marked-string (lsp:markup-content-value contents) lsp/markup-kind-markdown))
+ ((and (lsp-markup-content? contents)
+ (string= (lsp:markup-content-kind contents) lsp/markup-kind-plain-text))
+ (lsp:markup-content-value contents))))
+
+(defun lsp-ui-doc--webkit-run-xwidget ()
+ "Launch embedded WebKit instance."
+ (lsp-ui-doc--with-buffer
+ (let ((inhibit-read-only t))
+ (insert " ")
+ (goto-char 1)
+ (let ((id (make-xwidget 'webkit nil 1 1 nil (buffer-name))))
+ (set-xwidget-query-on-exit-flag id nil)
+ (put-text-property (point) (+ 1 (point))
+ 'display (list 'xwidget ':xwidget id))
+ (xwidget-webkit-mode)
+ (xwidget-webkit-goto-uri (xwidget-at 1)
+ lsp-ui-doc-webkit-client-path)
+ (lsp-ui-doc--webkit-set-background)
+ (lsp-ui-doc--webkit-set-foreground)))))
+
+(defun lsp-ui-doc--webkit-set-background ()
+ "Set background color of the WebKit widget."
+ (lsp-ui-doc--webkit-execute-script
+ (format "document.body.style.background = '%s';"
+ "#fdfdfd"
+ ;; (face-attribute 'lsp-ui-doc-background :background)
+ )))
+
+(defun lsp-ui-doc--webkit-set-foreground ()
+ "Set foreground color of the WebKit widget."
+ (lsp-ui-doc--webkit-execute-script
+ (format "document.body.style.color = '%s';"
+ (face-attribute 'default :foreground))))
+
+(defun lsp-ui-doc--webkit-get-xwidget ()
+ "Return Xwidget instance."
+ (lsp-ui-doc--with-buffer
+ (xwidget-at 1)))
+
+(defun lsp-ui-doc--webkit-execute-script (script &optional fn)
+ "Execute SCRIPT in embedded Xwidget and run optional callback FN."
+ (-when-let* ((xw (lsp-ui-doc--webkit-get-xwidget)))
+ (xwidget-webkit-execute-script xw script fn)))
+
+(defun lsp-ui-doc--webkit-execute-script-rv (script)
+ "Execute SCRIPT in embedded Xwidget synchronously."
+ (-when-let* ((xw (lsp-ui-doc--webkit-get-xwidget)))
+ (xwidget-webkit-execute-script-rv xw script)))
+
+(defun lsp-ui-doc--hide-frame (&optional _win)
+ "Hide the frame."
+ (setq lsp-ui-doc--bounds nil
+ lsp-ui-doc--from-mouse nil)
+ (lsp-ui-util-safe-delete-overlay lsp-ui-doc--inline-ov)
+ (lsp-ui-util-safe-delete-overlay lsp-ui-doc--highlight-ov)
+ (when-let ((frame (lsp-ui-doc--get-frame)))
+ (unless lsp-ui-doc-use-webkit
+ (lsp-ui-doc--with-buffer (erase-buffer)))
+ (when (frame-visible-p frame)
+ (make-frame-invisible frame))))
+
+(defun lsp-ui-doc--buffer-width ()
+ "Calcul the max width of the buffer."
+ (lsp-ui-doc--with-buffer
+ (save-excursion
+ (let ((max 0))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let* ((len (- (line-end-position) (line-beginning-position))))
+ (when (> len max)
+ (setq max len)))
+ (forward-line 1))
+ max))))
+
+(defun lsp-ui-doc--line-height (&optional line)
+ "Return the pos-y of the LINE on screen, in pixel."
+ (or
+ (nth 2 (or (window-line-height line)
+ (and (redisplay t)
+ (window-line-height line))))
+ 0))
+
+(defun lsp-ui-doc--sideline-pos-y ()
+ "Mark as unused function."
+ (-> (when (bound-and-true-p lsp-ui-sideline--occupied-lines)
+ (-min lsp-ui-sideline--occupied-lines))
+ (line-number-at-pos)
+ (lsp-ui-doc--line-height)))
+
+(defun lsp-ui-doc--webkit-resize-callback (size)
+ "Callback when resizing using webkit depends on the SIZE."
+ (let ((offset-width (round (aref size 0)))
+ (offset-height (round (aref size 1))))
+ (xwidget-resize (lsp-ui-doc--webkit-get-xwidget) offset-width offset-height))
+ (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame)))
+
+(defun lsp-ui-doc--resize-buffer ()
+ "If the buffer's width is larger than the current frame, resize it."
+ (if lsp-ui-doc-use-webkit
+ (lsp-ui-doc--webkit-execute-script
+ "[document.querySelector('#lsp-ui-webkit').offsetWidth, document.querySelector('#lsp-ui-webkit').offsetHeight];"
+ 'lsp-ui-doc--webkit-resize-callback)
+
+ (let* ((frame-width (frame-width))
+ (fill-column (min lsp-ui-doc-max-width (- frame-width 5))))
+ (when (> (lsp-ui-doc--buffer-width) (min lsp-ui-doc-max-width frame-width))
+ (lsp-ui-doc--with-buffer
+ (fill-region (point-min) (point-max)))))))
+
+(defun lsp-ui-doc--mv-at-point (width height start-x start-y)
+ "Return position of FRAME to be where the point is.
+WIDTH is the child frame width.
+HEIGHT is the child frame height.
+START-X is the position x of the current window.
+START-Y is the position y of the current window.
+The algorithm prefers to position FRAME just above the
+symbol at point, to not obstruct the view of the code that follows.
+If there's no space above in the current window, it places
+FRAME just below the symbol at point."
+ (-let* (((x . y) (--> (or lsp-ui-doc--bounds (bounds-of-thing-at-point 'symbol))
+ (or (posn-x-y (posn-at-point (car it)))
+ (if (< (car it) (window-start))
+ (cons 0 0)
+ (posn-x-y (posn-at-point (1- (window-end))))))))
+ (frame-relative-symbol-x (+ start-x x (* (frame-char-width) 2)))
+ (frame-relative-symbol-y (+ start-y y))
+ (char-height (frame-char-height))
+ ;; Make sure the frame is positioned horizontally such that
+ ;; it does not go beyond the frame boundaries.
+ (frame-x (or (and (<= (frame-outer-width) (+ frame-relative-symbol-x width))
+ (- x (- (+ frame-relative-symbol-x width)
+ (frame-outer-width))))
+ x))
+ (frame-y (+ (or (and (<= height frame-relative-symbol-y)
+ (- y height))
+ (+ y char-height))
+ (if (fboundp 'window-tab-line-height) (window-tab-line-height) 0))))
+ (cons (+ start-x frame-x) (+ start-y frame-y))))
+
+(defun lsp-ui-doc--size-and-pos-changed (frame left top width height)
+ (-let (((prev-left . prev-top) (frame-position frame)))
+ (not (and (= left prev-left)
+ (= top prev-top)
+ (= height (frame-text-height frame))
+ (= width (frame-text-width frame))))))
+
+(defun lsp-ui-doc--move-frame (frame)
+ "Place our FRAME on screen."
+ (-let* (((left top right _bottom) (window-edges nil t nil t))
+ (window (frame-root-window frame))
+ (char-h (frame-char-height frame))
+ (char-w (frame-char-width frame))
+ ((width . height) (window-text-pixel-size window nil nil 10000 10000 t))
+ (width (+ width (* char-w 1))) ;; margins
+ (height (min (- (* lsp-ui-doc-max-height char-h) (/ char-h 2)) height))
+ (width (min width (* lsp-ui-doc-max-width char-w)))
+ (frame-right (pcase lsp-ui-doc-alignment
+ ('frame (frame-pixel-width))
+ ('window right)))
+ ((left . top) (if (eq lsp-ui-doc-position 'at-point)
+ (lsp-ui-doc--mv-at-point width height left top)
+ (cons (max (- frame-right width char-w) 10)
+ (pcase lsp-ui-doc-position
+ ('top (+ top char-w))
+ ('bottom (- (lsp-ui-doc--line-height 'mode-line)
+ height
+ 10))))))
+ (frame-resize-pixelwise t)
+ (move-frame-functions nil)
+ (window-size-change-functions nil)
+ (window-state-change-hook nil)
+ (window-state-change-functions nil)
+ (window-configuration-change-hook nil)
+ (inhibit-redisplay t))
+ ;; Dirty way to fix unused variable in emacs 26
+ (and window-state-change-functions
+ window-state-change-hook)
+ ;; Make frame invisible before moving/resizing it to avoid flickering:
+ ;; We set the position and size in 1 call, modify-frame-parameters, but
+ ;; internally emacs makes 2 different calls, which can be visible
+ ;; to the user
+ (and (frame-visible-p frame)
+ (lsp-ui-doc--size-and-pos-changed frame left top width height)
+ (make-frame-invisible frame))
+ (modify-frame-parameters
+ frame
+ `((width . (text-pixels . ,width))
+ (height . (text-pixels . ,height))
+ (user-size . t)
+ (left . (+ ,left))
+ (top . (+ ,top))
+ (user-position . t)
+ (lsp-ui-doc--window-origin . ,(selected-window))
+ (lsp-ui-doc--buffer-origin . ,(current-buffer))
+ (lsp-ui-doc--no-focus . t)
+ (right-fringe . 0)
+ (left-fringe . 0)))
+ ;; Insert hr lines after width is computed
+ (lsp-ui-doc--fix-hr-props)
+ (unless (frame-visible-p frame)
+ (make-frame-visible frame))))
+
+(defun lsp-ui-doc--visit-file (filename)
+ "Visit FILENAME in the parent frame."
+ (-some->> (find-file-noselect filename)
+ (set-window-buffer (lsp-ui-doc--get-parent :window))))
+
+(defun lsp-ui-doc--put-click (start end fn)
+ "Add text properties on text to make it clickable.
+The text delimiters bound from START to END.
+FN is the function to call on click."
+ (let ((map (make-sparse-keymap)))
+ (define-key map [down-mouse-1] fn)
+ (put-text-property start end 'keymap map)
+ (put-text-property start end 'mouse-face
+ (list :inherit 'lsp-ui-doc-url
+ :box (list :line-width -1
+ :color (face-foreground 'lsp-ui-doc-url))))
+ (add-face-text-property start end 'lsp-ui-doc-url)))
+
+(defun lsp-ui-doc--open-markdown-link (&rest _)
+ (interactive "P")
+ (let ((buffer-list-update-hook nil))
+ (-let [(buffer point) (if-let* ((valid (and (listp last-input-event)
+ (eq (car last-input-event) 'mouse-2)))
+ (event (cadr last-input-event))
+ (win (posn-window event))
+ (buffer (window-buffer win)))
+ `(,buffer ,(posn-point event))
+ `(,(current-buffer) ,(point)))]
+ (with-current-buffer buffer
+ ;; Markdown-mode puts the url in 'help-echo
+ (-some--> (get-text-property point 'help-echo)
+ (and (string-match-p goto-address-url-regexp it)
+ (browse-url it)))))))
+
+(defun lsp-ui-doc--make-clickable-link ()
+ "Find paths and urls in the buffer and make them clickable."
+ (goto-char (point-min))
+ (save-excursion
+ (goto-char (point-min))
+ (let (case-fold-search)
+ (while (re-search-forward goto-address-url-regexp nil t)
+ (goto-char (1+ (match-end 0)))
+ (lsp-ui-doc--put-click (match-beginning 0) (match-end 0)
+ 'browse-url-at-mouse)))))
+
+(defun lsp-ui-doc--buffer-pre-command (&rest _)
+ (and (not (eq this-command 'mwheel-scroll))
+ (frame-parameter nil 'lsp-ui-doc--no-focus)
+ (select-frame (frame-parent) t)))
+
+(defun lsp-ui-doc--fill-document ()
+ "Better wrap the document so it fits the doc window."
+ (let ((fill-column (- lsp-ui-doc-max-width 5))
+ start ; record start for `fill-region'
+ first-line) ; first line in paragraph
+ (save-excursion
+ (goto-char (point-min))
+ (setq start (point)
+ first-line (thing-at-point 'line))
+ (while (re-search-forward "^[ \t]*\n" nil t)
+ (setq first-line (thing-at-point 'line))
+ (when (< fill-column (length first-line))
+ (fill-region start (point)))
+ (setq start (point)))
+ ;; Fill the last paragraph
+ (when (< fill-column (length first-line))
+ (fill-region start (point-max))))))
+
+(defun lsp-ui-doc--make-smaller-empty-lines nil
+ "Make empty lines half normal lines."
+ (progn ; Customize line before header
+ (goto-char 1)
+ (insert (propertize "\n" 'face '(:height 0.3))))
+ (progn ; Customize line after header
+ (forward-line 1)
+ (insert (propertize " " 'face '(:height 0.1))))
+ (while (not (eobp))
+ (when (and (eolp) (not (bobp)))
+ (save-excursion
+ (delete-region (point) (progn (forward-visible-line 1) (point))))
+ (when (or (and (not (get-text-property (point) 'markdown-heading))
+ (not (get-text-property (max (- (point) 2) 1) 'markdown-heading)))
+ (get-text-property (point) 'markdown-hr))
+ (insert (propertize " " 'face `(:height 0.2))
+ (propertize "\n" 'face '(:height 0.4)))))
+ (forward-line))
+ (insert (propertize "\n\n" 'face '(:height 0.3))))
+
+(defun lsp-ui-doc--fix-hr-props nil
+ ;; We insert the right display prop after window-text-pixel-size
+ (lsp-ui-doc--with-buffer
+ (let (next)
+ (while (setq next (next-single-property-change (or next 1) 'lsp-ui-doc--replace-hr))
+ (when (get-text-property next 'lsp-ui-doc--replace-hr)
+ (put-text-property next (1+ next) 'display
+ '(space :align-to (- right-fringe 1) :height (1)))
+ (put-text-property (1+ next) (+ next 2) 'display
+ '(space :align-to right-fringe :height (1))))))))
+
+(defun lsp-ui-doc--handle-hr-lines nil
+ (let (bolp next before after)
+ (goto-char 1)
+ (while (setq next (next-single-property-change (or next 1) 'markdown-hr))
+ (when (get-text-property next 'markdown-hr)
+ (goto-char next)
+ (setq bolp (bolp)
+ before (char-before))
+ (delete-region (point) (save-excursion (forward-visible-line 1) (point)))
+ (setq after (char-after (1+ (point))))
+ (insert
+ (concat
+ (and bolp (not (equal before ?\n)) (propertize "\n" 'face '(:height 0.5)))
+ (propertize " "
+ ;; :align-to is added with lsp-ui-doc--fix-hr-props
+ 'display '(space :height (1))
+ 'lsp-ui-doc--replace-hr t
+ 'face '(:background "dark grey"))
+ ;; :align-to is added here too
+ (propertize " " 'display '(space :height (1)))
+ (and (not (equal after ?\n)) (propertize " \n" 'face '(:height 0.2)))))))))
+
+(defun lsp-ui-doc--render-buffer (string symbol)
+ "Set the buffer with STRING and SYMBOL."
+ (lsp-ui-doc--with-buffer
+ (if lsp-ui-doc-use-webkit
+ (progn
+ (lsp-ui-doc--webkit-execute-script
+ (format "renderMarkdown('%s', '%s');"
+ symbol
+ (url-hexify-string string))
+ 'lsp-ui-doc--webkit-resize-callback))
+ (erase-buffer)
+ (insert (s-trim string))
+ (unless (lsp-ui-doc--inline-p)
+ (lsp-ui-doc--fill-document)
+ (lsp-ui-doc--make-smaller-empty-lines)
+ (lsp-ui-doc--handle-hr-lines))
+ (add-text-properties 1 (point) '(line-height 1))
+ (lsp-ui-doc--make-clickable-link)
+ (add-text-properties 1 (point-max) '(pointer arrow)))
+ (lsp-ui-doc-frame-mode 1)
+ (setq wrap-prefix '(space :height (1) :width 1)
+ line-prefix '(space :height (1) :width 1))
+ (setq-local face-remapping-alist `((header-line lsp-ui-doc-header)))
+ (setq-local window-min-height 1)
+ (setq-local show-trailing-whitespace nil)
+ (setq-local window-configuration-change-hook nil)
+ (add-hook 'pre-command-hook 'lsp-ui-doc--buffer-pre-command nil t)
+ (when (boundp 'window-state-change-functions)
+ (setq-local window-state-change-functions nil))
+ (when (boundp 'window-state-change-hook)
+ (setq-local window-state-change-hook nil))
+ (setq-local window-size-change-functions nil)
+ (setq header-line-format (when lsp-ui-doc-header (concat " " symbol))
+ mode-line-format nil
+ cursor-type nil)))
+
+(defun lsp-ui-doc--inline-height ()
+ (lsp-ui-doc--with-buffer
+ (length (split-string (buffer-string) "\n"))))
+
+(defun lsp-ui-doc--remove-invisibles (string)
+ "Remove invisible characters in STRING."
+ (let* ((start (text-property-not-all 0 (length string) 'invisible nil string)))
+ (while start
+ (setq string (concat (substring string 0 start)
+ (-some->> (next-single-property-change start 'invisible string)
+ (substring string))))
+ (setq start (text-property-not-all 0 (length string) 'invisible nil string)))
+ string))
+
+(defvar-local lsp-ui-doc--inline-width nil)
+
+(defun lsp-ui-doc--inline-window-width nil
+ (- (min (window-text-width) (window-body-width))
+ (if (bound-and-true-p display-line-numbers-mode)
+ (+ 2 (line-number-display-width))
+ 0)
+ 1))
+
+(defun lsp-ui-doc--inline-zip (s1 s2)
+ (let* ((width (lsp-ui-doc--inline-window-width))
+ (max-s1 (- width lsp-ui-doc--inline-width 2)))
+ (truncate-string-to-width
+ (concat (truncate-string-to-width s1 max-s1 nil ?\s) s2)
+ width nil ?\s)))
+
+(defun lsp-ui-doc--inline-padding (string len)
+ (let ((string (concat " " string (make-string (- len (string-width string)) ?\s) " ")))
+ (add-face-text-property 0 (length string) (list :background (face-background 'lsp-ui-doc-background nil t)) t string)
+ string))
+
+(defun lsp-ui-doc--inline-faking-frame (doc-strings)
+ (let* ((len-max (-max-by '> (-map 'string-width doc-strings))))
+ (setq lsp-ui-doc--inline-width len-max)
+ (--map (lsp-ui-doc--inline-padding it len-max) doc-strings)))
+
+(defun lsp-ui-doc--inline-untab (string)
+ (replace-regexp-in-string "\t" (make-string tab-width ?\s) string nil t))
+
+(defun lsp-ui-doc--inline-merge (strings)
+ (let* ((buffer-strings (-> (lsp-ui-doc--inline-untab strings)
+ (lsp-ui-doc--remove-invisibles)
+ (split-string "\n")))
+ (doc-strings (-> (lsp-ui-doc--with-buffer (buffer-string))
+ (lsp-ui-doc--inline-untab)
+ (lsp-ui-doc--remove-invisibles)
+ (split-string "\n")))
+ (merged (--> (lsp-ui-doc--inline-faking-frame doc-strings)
+ (-zip-with 'lsp-ui-doc--inline-zip buffer-strings it)
+ (string-join it "\n")
+ (concat it "\n"))))
+ merged))
+
+(defun lsp-ui-doc--inline-pos-at (start lines)
+ "Calcul the position at START + forward n LINES."
+ (save-excursion (goto-char start) (forward-line lines) (point)))
+
+(defun lsp-ui-doc--inline-pos (height)
+ "Return a cons of positions where to place the doc.
+HEIGHT is the documentation number of lines."
+ (let* ((w-start (window-start))
+ (w-end (lsp-ui-doc--inline-pos-at w-start (window-body-height)))
+ (ov-end (lsp-ui-doc--inline-pos-at w-start height)))
+ (cond
+ ;; Display on top ?
+ ((< (lsp-ui-doc--inline-pos-at ov-end 1) (point))
+ (cons w-start ov-end))
+ ;; Display at the bottom ?
+ ((>= (lsp-ui-doc--inline-pos-at w-end (- height))
+ (lsp-ui-doc--inline-pos-at (point) 2))
+ (cons (lsp-ui-doc--inline-pos-at w-end (- height))
+ w-end))
+ ;; The doc is too long to display it fixed to the bottom ?
+ ;; Then display 2 lines after `point'
+ ;; The end of the documentation won't be visible in the window
+ (t (cons (lsp-ui-doc--inline-pos-at (point) 2)
+ (lsp-ui-doc--inline-pos-at (point) (+ height 2)))))))
+
+(defun lsp-ui-doc--inline ()
+ "Display the doc in the buffer."
+ (-let* ((height (lsp-ui-doc--inline-height))
+ ((start . end) (lsp-ui-doc--inline-pos height))
+ (buffer-string (buffer-substring start end))
+ (ov (if (overlayp lsp-ui-doc--inline-ov) lsp-ui-doc--inline-ov
+ (setq lsp-ui-doc--inline-ov (make-overlay start end)))))
+ (move-overlay ov start end)
+ (overlay-put ov 'face 'default)
+ (overlay-put ov 'display (lsp-ui-doc--inline-merge buffer-string))
+ (overlay-put ov 'lsp-ui-doc-inline t)
+ (overlay-put ov 'window (selected-window))))
+
+(defun lsp-ui-doc--inline-p ()
+ "Return non-nil when the documentation should be display without a child frame."
+ (or (not lsp-ui-doc-use-childframe)
+ (not (display-graphic-p))
+ (not (fboundp 'display-buffer-in-child-frame))))
+
+(defun lsp-ui-doc--highlight-hover nil
+ (when lsp-ui-doc--from-mouse-current
+ (-let* (((start . end) lsp-ui-doc--bounds)
+ (ov (if (overlayp lsp-ui-doc--highlight-ov) lsp-ui-doc--highlight-ov
+ (setq lsp-ui-doc--highlight-ov (make-overlay start end)))))
+ (move-overlay ov start end)
+ (overlay-put ov 'face 'lsp-ui-doc-highlight-hover)
+ (overlay-put ov 'window (selected-window)))))
+
+(defun lsp-ui-doc--display (symbol string)
+ "Display the documentation."
+ (when (and lsp-ui-doc-use-webkit (not (featurep 'xwidget-internal)))
+ (setq lsp-ui-doc-use-webkit nil))
+ (if (or (null string) (string-empty-p string))
+ (lsp-ui-doc--hide-frame)
+ (lsp-ui-doc--highlight-hover)
+ (lsp-ui-doc--render-buffer string symbol)
+ (if (lsp-ui-doc--inline-p)
+ (lsp-ui-doc--inline)
+ (unless (lsp-ui-doc--get-frame)
+ (lsp-ui-doc--set-frame (lsp-ui-doc--make-frame)))
+ (unless lsp-ui-doc-use-webkit
+ (lsp-ui-doc--resize-buffer)
+ (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame))))
+ (setq lsp-ui-doc--from-mouse lsp-ui-doc--from-mouse-current)))
+
+(defun lsp-ui-doc--make-frame ()
+ "Create the child frame and return it."
+ (lsp-ui-doc--delete-frame)
+ (let* ((after-make-frame-functions nil)
+ (before-make-frame-hook nil)
+ (name-buffer (lsp-ui-doc--make-buffer-name))
+ (buffer (get-buffer name-buffer))
+ (params (append lsp-ui-doc-frame-parameters
+ `((name . "")
+ (default-minibuffer-frame . ,(selected-frame))
+ (minibuffer . ,(minibuffer-window))
+ (left-fringe . 0)
+ (right-fringe . 0)
+ (cursor-type . nil)
+ (lsp-ui-doc--no-focus . t)
+ (background-color . ,(face-background 'lsp-ui-doc-background nil t)))))
+ (window (display-buffer-in-child-frame
+ buffer
+ `((child-frame-parameters . ,params))))
+ (frame (window-frame window)))
+ (with-current-buffer buffer
+ (lsp-ui-doc-frame-mode 1))
+ (set-frame-parameter nil 'lsp-ui-doc-buffer buffer)
+ (set-window-dedicated-p window t)
+ ;;(redirect-frame-focus frame (frame-parent frame))
+ (set-face-background 'internal-border lsp-ui-doc-border frame)
+ (when (facep 'child-frame-border)
+ (set-face-background 'child-frame-border lsp-ui-doc-border frame))
+ (set-face-background 'fringe nil frame)
+ (run-hook-with-args 'lsp-ui-doc-frame-hook frame window)
+ (when lsp-ui-doc-use-webkit
+ (define-key (current-global-map) [xwidget-event]
+ (lambda ()
+ (interactive)
+ (let ((xwidget-event-type (nth 1 last-input-event)))
+ ;; (when (eq xwidget-event-type 'load-changed)
+ ;; (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame)))
+ (when (eq xwidget-event-type 'javascript-callback)
+ (let ((proc (nth 3 last-input-event))
+ (arg (nth 4 last-input-event)))
+ (funcall proc arg))))))
+ (lsp-ui-doc--webkit-run-xwidget))
+ frame))
+
+(defconst lsp-ui-doc--ignore-commands
+ '(lsp-ui-doc-hide
+ lsp-ui-doc--handle-mouse-movement
+ keyboard-quit
+ ignore
+ handle-switch-frame
+ mwheel-scroll))
+
+(defun lsp-ui-doc--make-request nil
+ "Request the documentation to the LS."
+ (and (not track-mouse) lsp-ui-doc-show-with-mouse (setq-local track-mouse t))
+ (when (and lsp-ui-doc-show-with-cursor
+ (not (memq this-command lsp-ui-doc--ignore-commands))
+ (not (bound-and-true-p lsp-ui-peek-mode))
+ (lsp--capability "hoverProvider"))
+ (-if-let (bounds (or (and (symbol-at-point) (bounds-of-thing-at-point 'symbol))
+ (and (looking-at "[[:graph:]]") (cons (point) (1+ (point))))))
+ (unless (equal lsp-ui-doc--bounds bounds)
+ (lsp-ui-doc--hide-frame)
+ (lsp-ui-util-safe-kill-timer lsp-ui-doc--timer)
+ (setq lsp-ui-doc--timer
+ (run-with-idle-timer
+ lsp-ui-doc-delay nil
+ (let ((buf (current-buffer)))
+ (lambda nil
+ (when (equal buf (current-buffer))
+ (lsp-request-async
+ "textDocument/hover"
+ (lsp--text-document-position-params)
+ (lambda (hover)
+ (when (equal buf (current-buffer))
+ (lsp-ui-doc--callback hover bounds (current-buffer))))
+ :mode 'tick
+ :cancel-token :lsp-ui-doc-hover)))))))
+ (lsp-ui-doc--hide-frame))))
+
+(defun lsp-ui-doc--extract-bounds (hover)
+ (-when-let* ((hover hover)
+ (data (lsp-get hover :range))
+ (start (-some-> (lsp:range-start data) lsp--position-to-point))
+ (end (-some-> (lsp:range-end data) lsp--position-to-point)))
+ (cons start end)))
+
+(lsp-defun lsp-ui-doc--callback ((hover &as &Hover? :contents) bounds buffer)
+ "Process the received documentation.
+HOVER is the doc returned by the LS.
+BOUNDS are points of the symbol that have been requested.
+BUFFER is the buffer where the request has been made."
+ (let ((bounds (or (lsp-ui-doc--extract-bounds hover) bounds)))
+ (if (and hover
+ (>= (point) (car bounds))
+ (<= (point) (cdr bounds))
+ (eq buffer (current-buffer)))
+ (progn
+ (setq lsp-ui-doc--bounds bounds)
+ (lsp-ui-doc--display
+ (thing-at-point 'symbol t)
+ (-some->> contents
+ lsp-ui-doc--extract
+ (replace-regexp-in-string "\r" "")
+ (replace-regexp-in-string " " " "))))
+ (lsp-ui-doc--hide-frame))))
+
+(defun lsp-ui-doc--delete-frame ()
+ "Delete the child frame if it exists."
+ (-when-let (frame (lsp-ui-doc--get-frame))
+ (delete-frame frame)
+ (lsp-ui-doc--set-frame nil)))
+
+(defun lsp-ui-doc--visible-p ()
+ "Return whether the LSP UI doc is visible"
+ (or (overlayp lsp-ui-doc--inline-ov)
+ (and (lsp-ui-doc--get-frame)
+ (frame-visible-p (lsp-ui-doc--get-frame)))))
+
+(defun lsp-ui-doc-hide-frame-on-window-change (fun window &optional no-record)
+ "Delete the child frame if currently selected window changes.
+Does nothing if the newly-selected window is the same window as
+before, or if the new window is the minibuffer."
+ (let ((initial-window (selected-window)))
+ (prog1 (funcall fun window no-record)
+ (unless no-record
+ (when (lsp-ui-doc--visible-p)
+ (let* ((current-window (selected-window))
+ (doc-buffer (get-buffer (lsp-ui-doc--make-buffer-name))))
+ (unless (or (window-minibuffer-p current-window)
+ (equal current-window initial-window)
+ (and doc-buffer
+ (equal (window-buffer initial-window) doc-buffer)))
+ (lsp-ui-doc--hide-frame))))))))
+
+(unless (boundp 'window-state-change-functions)
+ (advice-add #'select-window :around #'lsp-ui-doc-hide-frame-on-window-change)
+ (add-hook 'window-configuration-change-hook #'lsp-ui-doc--hide-frame))
+
+(defvar-local lsp-ui-doc--timer-on-changes nil)
+
+(defun lsp-ui-doc--on-state-changed (_frame &optional on-idle)
+ (-when-let* ((frame (lsp-ui-doc--get-frame)))
+ (and (frame-live-p frame)
+ (frame-visible-p frame)
+ (not (minibufferp (window-buffer)))
+ (or (not (eq (selected-window) (frame-parameter frame 'lsp-ui-doc--window-origin)))
+ (not (eq (window-buffer) (frame-parameter frame 'lsp-ui-doc--buffer-origin))))
+ (if on-idle (lsp-ui-doc--hide-frame)
+ (and (timerp lsp-ui-doc--timer-on-changes)
+ (cancel-timer lsp-ui-doc--timer-on-changes))
+ (setq lsp-ui-doc--timer-on-changes
+ (run-with-idle-timer 0 nil (lambda nil (lsp-ui-doc--on-state-changed frame t))))))))
+
+(advice-add 'load-theme :before (lambda (&rest _) (lsp-ui-doc--delete-frame)))
+
+(advice-add #'keyboard-quit :before #'lsp-ui-doc--hide-frame)
+
+(defun lsp-ui-doc--on-delete (frame)
+ "Function called when a FRAME is deleted."
+ (-some--> (frame-parameter frame 'lsp-ui-doc-buffer)
+ (get-buffer it)
+ (and (buffer-live-p it) it)
+ (kill-buffer it)))
+
+(defun lsp-ui-doc--handle-scroll (win _new-start)
+ "Handle scrolling to the document frame.
+
+This function is apply to hook `window-scroll-functions'.
+
+Argument WIN is current applying window."
+ (let ((frame (lsp-ui-doc--get-frame)))
+ (if (minibufferp (window-buffer))
+ (lsp-ui-doc--hide-frame)
+ (when (and frame
+ (eq lsp-ui-doc-position 'at-point)
+ (frame-visible-p frame)
+ (eq win (selected-window))) ; This resolved #524
+ (if (and lsp-ui-doc--bounds
+ (eq (window-buffer) (frame-parameter frame 'lsp-ui-doc--buffer-origin))
+ (>= (point) (car lsp-ui-doc--bounds))
+ (<= (point) (cdr lsp-ui-doc--bounds)))
+ (lsp-ui-doc--move-frame frame)
+ ;; The point might have changed if the window was scrolled
+ ;; too far
+ (lsp-ui-doc--hide-frame))))))
+
+(defvar-local lsp-ui-doc--timer-mouse-movement nil)
+(defvar-local lsp-ui-doc--last-event nil)
+
+(defun lsp-ui-doc--mouse-display nil
+ (when (and lsp-ui-doc--last-event
+ (lsp-feature? "textDocument/hover"))
+ (save-excursion
+ (goto-char lsp-ui-doc--last-event)
+ (-when-let* ((valid (not (eolp)))
+ (bounds (or (and (symbol-at-point) (bounds-of-thing-at-point 'symbol))
+ (and (looking-at "[[:graph:]]") (cons (point) (1+ (point)))))))
+ (unless (equal bounds lsp-ui-doc--bounds)
+ (lsp-request-async
+ "textDocument/hover"
+ (lsp--text-document-position-params)
+ (lambda (hover)
+ (save-excursion
+ (goto-char lsp-ui-doc--last-event)
+ (let ((lsp-ui-doc-position 'at-point)
+ (lsp-ui-doc--from-mouse-current t))
+ (lsp-ui-doc--callback hover bounds (current-buffer)))))
+ :mode 'tick
+ :cancel-token :lsp-ui-doc-hover))))))
+
+(defun lsp-ui-doc--handle-mouse-movement (event)
+ "Show the documentation corresponding to the text under EVENT."
+ (interactive "e")
+ (when lsp-ui-doc-show-with-mouse
+ (and (timerp lsp-ui-doc--timer-mouse-movement)
+ (cancel-timer lsp-ui-doc--timer-mouse-movement))
+ (let* ((e (cadr event))
+ (point (posn-point e))
+ (same-win (eq (selected-window) (posn-window e))))
+ (and lsp-ui-doc--from-mouse
+ lsp-ui-doc--bounds
+ point
+ (or (< point (car lsp-ui-doc--bounds))
+ (> point (cdr lsp-ui-doc--bounds))
+ (not same-win)
+ (equal (char-after point) ?\n))
+ (lsp-ui-doc--hide-frame))
+ (when same-win
+ (setq lsp-ui-doc--last-event point
+ lsp-ui-doc--timer-mouse-movement
+ (run-with-idle-timer 0.5 nil 'lsp-ui-doc--mouse-display))))))
+
+(defun lsp-ui-doc--disable-mouse-on-prefix nil
+ (and (bound-and-true-p lsp-ui-doc-mode)
+ (bound-and-true-p lsp-ui-doc--mouse-tracked-by-us)
+ track-mouse
+ (> (length (this-single-command-keys)) 0)
+ (setq-local track-mouse nil)))
+
+(defvar lsp-ui-doc--timer-mouse-idle nil)
+
+(defvar-local lsp-ui-doc--mouse-tracked-by-us nil
+ "Nil if `track-mouse' was set by another package.
+If nil, do not prevent mouse on prefix keys.")
+
+(defun lsp-ui-doc--setup-mouse nil
+ (when lsp-ui-doc-show-with-mouse
+ (setq lsp-ui-doc--mouse-tracked-by-us (not track-mouse))
+ (setq-local track-mouse t)
+ (unless lsp-ui-doc--timer-mouse-idle
+ ;; Set only 1 timer for all buffers
+ (setq lsp-ui-doc--timer-mouse-idle
+ (run-with-idle-timer 0 t 'lsp-ui-doc--disable-mouse-on-prefix)))))
+
+(defun lsp-ui-doc--prevent-focus-doc (e)
+ (not (frame-parameter (cadr e) 'lsp-ui-doc--no-focus)))
+
+(define-minor-mode lsp-ui-doc-mode
+ "Minor mode for showing hover information in child frame."
+ :init-value nil
+ :keymap `((,(kbd "<mouse-movement>") . lsp-ui-doc--handle-mouse-movement))
+ :group lsp-ui-doc
+ (cond
+ (lsp-ui-doc-mode
+ (with-eval-after-load 'frameset
+ ;; The documentation frame can’t be properly restored. Especially
+ ;; ‘desktop-save’ will misbehave and save a bogus string "Unprintable
+ ;; entity" in the desktop file. Therefore we have to prevent
+ ;; ‘frameset-save’ from saving the parameter.
+ (unless (assq 'lsp-ui-doc-frame frameset-filter-alist)
+ ;; Copy the variable first. See the documentation of
+ ;; ‘frameset-filter-alist’ for explanation.
+ (cl-callf copy-tree frameset-filter-alist)
+ (push '(lsp-ui-doc-frame . :never) frameset-filter-alist)))
+ (when (boundp 'window-state-change-functions)
+ (add-hook 'window-state-change-functions 'lsp-ui-doc--on-state-changed))
+ (lsp-ui-doc--setup-mouse)
+ (advice-add 'handle-switch-frame :before-while 'lsp-ui-doc--prevent-focus-doc)
+ (add-hook 'post-command-hook 'lsp-ui-doc--make-request nil t)
+ (add-hook 'window-scroll-functions 'lsp-ui-doc--handle-scroll nil t)
+ (add-hook 'delete-frame-functions 'lsp-ui-doc--on-delete nil t))
+ (t
+ (lsp-ui-doc-hide)
+ (when (boundp 'window-state-change-functions)
+ (remove-hook 'window-state-change-functions 'lsp-ui-doc--on-state-changed))
+ (remove-hook 'window-scroll-functions 'lsp-ui-doc--handle-scroll t)
+ (remove-hook 'post-command-hook 'lsp-ui-doc--make-request t)
+ (remove-hook 'delete-frame-functions 'lsp-ui-doc--on-delete t))))
+
+(defun lsp-ui-doc-enable (enable)
+ "Enable/disable ‘lsp-ui-doc-mode’.
+It is supposed to be called from `lsp-ui--toggle'"
+ (lsp-ui-doc-mode (if enable 1 -1)))
+
+(defun lsp-ui-doc-show ()
+ "Trigger display hover information popup."
+ (interactive)
+ (lsp-ui-doc--callback (lsp-request "textDocument/hover" (lsp--text-document-position-params))
+ (or (bounds-of-thing-at-point 'symbol) (cons (point) (1+ (point))))
+ (current-buffer)))
+
+(defun lsp-ui-doc-hide ()
+ "Hide hover information popup."
+ (interactive)
+ (lsp-ui-doc--hide-frame))
+
+(defvar-local lsp-ui-doc--unfocus-frame-timer nil)
+(defun lsp-ui-doc--glance-hide-frame ()
+ "Hook to hide hover information popup for `lsp-ui-doc-glance'."
+ (when (or (overlayp lsp-ui-doc--inline-ov)
+ (lsp-ui-doc--frame-visible-p))
+ (lsp-ui-doc--hide-frame)
+ (remove-hook 'post-command-hook 'lsp-ui-doc--glance-hide-frame)
+ ;; make sure child frame is unfocused
+ (setq lsp-ui-doc--unfocus-frame-timer
+ (run-at-time 1 nil #'lsp-ui-doc-unfocus-frame))))
+
+(defun lsp-ui-doc-glance ()
+ "Trigger display hover information popup and hide it on next typing."
+ (interactive)
+ (lsp-ui-doc--make-request)
+ (when lsp-ui-doc--unfocus-frame-timer
+ (cancel-timer lsp-ui-doc--unfocus-frame-timer))
+ (add-hook 'post-command-hook 'lsp-ui-doc--glance-hide-frame))
+
+(define-minor-mode lsp-ui-doc-frame-mode
+ "Marker mode to add additional key bind for lsp-ui-doc-frame."
+ :init-value nil
+ :lighter ""
+ :group lsp-ui-doc
+ :keymap `(([?q] . lsp-ui-doc-unfocus-frame)
+ ([remap markdown-follow-thing-at-point] . lsp-ui-doc--open-markdown-link)
+ ([remap mouse-drag-region] . ignore)))
+
+(defun lsp-ui-doc-focus-frame ()
+ "Focus into lsp-ui-doc-frame."
+ (interactive)
+ (when-let* ((frame (lsp-ui-doc--get-frame))
+ (visible (lsp-ui-doc--frame-visible-p)))
+ (set-frame-parameter frame 'lsp-ui-doc--no-focus nil)
+ (set-frame-parameter frame 'cursor-type t)
+ (lsp-ui-doc--with-buffer
+ (setq cursor-type 'box))
+ (select-frame-set-input-focus frame)))
+
+(defun lsp-ui-doc-unfocus-frame ()
+ "Unfocus from lsp-ui-doc-frame."
+ (interactive)
+ (-some-> (frame-parent) select-frame-set-input-focus)
+ (when-let* ((frame (lsp-ui-doc--get-frame)))
+ (set-frame-parameter frame 'lsp-ui-doc--no-focus t)
+ (set-frame-parameter frame 'cursor-type nil)
+ (lsp-ui-doc--with-buffer
+ (setq cursor-type nil))
+ (when lsp-ui-doc--from-mouse
+ (make-frame-invisible frame))))
+
+(provide 'lsp-ui-doc)
+;;; lsp-ui-doc.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.html b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.html
new file mode 100644
index 0000000..1895ce7
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-doc.html
@@ -0,0 +1,43 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.0/showdown.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.css">
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/default.min.css">
+ <style>
+ .markdown-body {
+ box-sizing: border-box;
+ min-width: 400px;
+ max-width: 600px;
+ margin: 0 auto;
+ padding: 10px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="lsp-ui-webkit" class="markdown-body">
+ </div>
+ <script>
+ var converter = new showdown.Converter({simpleLineBreaks: true});
+ var lastSymbol = "";
+ var elem = document.getElementById('lsp-ui-webkit');
+
+ function renderMarkdown(symbol, markedString) {
+ if (symbol == lastSymbol) return [elem.offsetWidth, elem.offsetHeight];
+ decodedString = decodeURIComponent(markedString);
+ html = converter.makeHtml(decodedString);
+ elem.innerHTML = html;
+ lastSymbol = symbol;
+
+ document.querySelectorAll('pre code').forEach(function(codeBlock) {
+ hljs.highlightBlock(codeBlock);
+ });
+
+ return [elem.offsetWidth, elem.offsetHeight];
+ }
+
+ </script>
+ </body>
+</html>
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-flycheck.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-flycheck.el
new file mode 100644
index 0000000..e3ac831
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-flycheck.el
@@ -0,0 +1,171 @@
+;;; lsp-ui-flycheck.el --- Flycheck support for lsp-mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 fmdkdd
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languagues, tools
+;; Version: 6.2
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Flycheck integration for lsp-mode.
+
+;;; Code:
+
+(require 'flycheck nil 'noerror) ; Temporary solution, see #514
+(require 'pcase)
+(require 'dash)
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+
+(defgroup lsp-ui-flycheck nil
+ "The LSP extension to display syntax checking."
+ :group 'tools
+ :group 'convenience
+ :group 'lsp-ui
+ :link '(custom-manual "(lsp-ui-flycheck) Top")
+ :link '(info-link "(lsp-ui-flycheck) Customizing"))
+
+(defcustom lsp-ui-flycheck-list-position 'bottom
+ "Position where `lsp-ui-flycheck-list' will show diagnostics for the
+whole workspace."
+ :type '(choice (const :tag "Bottom" bottom)
+ (const :tag "Right" right))
+ :group 'lsp-ui-flycheck)
+
+(defvar-local lsp-ui-flycheck-list--buffer nil)
+(defvar-local lsp-ui-flycheck--save-mode nil)
+
+(defun lsp-ui-flycheck-list--post-command ()
+ (when (eobp)
+ (forward-line -1)))
+
+(defun lsp-ui-flycheck-list--update (window workspace)
+ "Update flycheck buffer in WINDOW belonging to WORKSPACE.
+Use `lsp-diagnostics' to receive diagnostics from your LSP server."
+ (let ((buffer-read-only nil)
+ (lsp--cur-workspace workspace))
+ (erase-buffer)
+ (remove-overlays)
+ (maphash (lambda (file diagnostic)
+ (when diagnostic
+ (overlay-put
+ (make-overlay (point) (point))
+ 'after-string
+ (concat (propertize "\n" 'face '(:height 0.2))
+ (propertize (lsp-ui--workspace-path file)
+ 'face 'dired-directory)
+ (propertize "\n" 'face '(:height 0.2)))))
+ (dolist (diag diagnostic)
+ (-let* (((&Diagnostic :message :severity? :source?
+ :range (&Range :start (&Position :line start-line))) diag)
+ (formatted-message (or (if source? (format "%s: %s" source? message) message) "???"))
+ (severity (or severity? 1))
+ (line (1+ start-line))
+ (face (cond ((= severity 1) 'error)
+ ((= severity 2) 'warning)
+ (t 'success)))
+ (text (concat (propertize (number-to-string line) 'face face)
+ ": "
+ (car (split-string formatted-message "\n")))))
+ (add-text-properties 0 (length text) `(diag ,diag file ,file window ,window) text)
+ (insert (concat text "\n")))))
+ (lsp-diagnostics)))
+ (if (= (point) 1)
+ (overlay-put (make-overlay 1 1)
+ 'after-string "No diagnostic available\n")
+ (goto-char 1))
+ (lsp-ui-flycheck-list-mode))
+
+(defun lsp-ui-flycheck-list ()
+ "List all the diagnostics in the whole workspace."
+ (interactive)
+ (let ((buffer (get-buffer-create "*lsp-diagnostics*"))
+ (workspace lsp--cur-workspace)
+ (window (selected-window)))
+ (with-current-buffer buffer
+ (lsp-ui-flycheck-list--update window workspace))
+ (add-hook 'lsp-diagnostics-updated-hook 'lsp-ui-flycheck-list--refresh nil t)
+ (setq lsp-ui-flycheck-list--buffer buffer)
+ (let ((win (display-buffer-in-side-window
+ buffer `((side . ,lsp-ui-flycheck-list-position) (slot . 5) (window-width . 0.20)))))
+ (set-window-dedicated-p win t)
+ (select-window win)
+ (fit-window-to-buffer nil nil 10))))
+
+(defun lsp-ui-flycheck-list--refresh ()
+ (let ((workspace lsp--cur-workspace)
+ (current-window (selected-window)))
+ (when (and (buffer-live-p lsp-ui-flycheck-list--buffer)
+ (get-buffer-window lsp-ui-flycheck-list--buffer)
+ workspace)
+ (with-selected-window (get-buffer-window lsp-ui-flycheck-list--buffer)
+ (lsp-ui-flycheck-list--update current-window workspace)
+ (fit-window-to-buffer nil nil 10)))))
+
+(defun lsp-ui-flycheck-list--open ()
+ (-when-let* ((diag (get-text-property (point) 'diag))
+ ((&Diagnostic :range (&Range :start (&Position :line start-line
+ :character start-column))) diag)
+ (file (get-text-property (point) 'file))
+ (window (get-text-property (point) 'window))
+ (marker (with-current-buffer
+ (or (get-file-buffer file)
+ (find-file-noselect file))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char 1)
+ (forward-line start-line)
+ (forward-char start-column)
+ (point-marker))))))
+ (set-window-buffer window (marker-buffer marker) t)
+ (with-selected-window window
+ (goto-char marker)
+ (recenter)
+ (pulse-momentary-highlight-one-line (marker-position marker) 'next-error))
+ window))
+
+(defun lsp-ui-flycheck-list--view ()
+ (interactive)
+ (lsp-ui-flycheck-list--open))
+
+(defun lsp-ui-flycheck-list--visit ()
+ (interactive)
+ (select-window (lsp-ui-flycheck-list--open)))
+
+(defun lsp-ui-flycheck-list--quit ()
+ (interactive)
+ (kill-buffer))
+
+(defvar lsp-ui-flycheck-list-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "q") 'lsp-ui-flycheck-list--quit)
+ (define-key map (kbd "<return>") 'lsp-ui-flycheck-list--view)
+ (define-key map (kbd "<M-return>") 'lsp-ui-flycheck-list--visit)
+ map)
+ "Keymap for ‘lsp-ui-flycheck-list-mode’.")
+
+(define-derived-mode lsp-ui-flycheck-list-mode special-mode "lsp-ui-flycheck-list"
+ "Mode showing flycheck diagnostics for the whole workspace."
+ (setq truncate-lines t)
+ (setq mode-line-format nil)
+ (add-hook 'post-command-hook 'lsp-ui-flycheck-list--post-command nil t))
+
+(declare-function lsp-ui--workspace-path "lsp-ui" (path))
+
+(provide 'lsp-ui-flycheck)
+;;; lsp-ui-flycheck.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-imenu.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-imenu.el
new file mode 100644
index 0000000..3c628da
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-imenu.el
@@ -0,0 +1,412 @@
+;;; lsp-ui-imenu.el --- Lsp-Ui-Imenu -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018 Sebastien Chapuis
+
+;; Author: Sebastien Chapuis <sebastien@chapu.is>
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languages, tools
+;; Version: 6.3
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Show imenu entries
+;; Call the function `lsp-ui-imenu'
+;;
+;; (define-key lsp-ui-mode-map (kbd "C-c l") 'lsp-ui-imenu)
+
+;;; Code:
+
+(require 'lsp-mode)
+(require 'dash)
+(require 'lsp-ui-util)
+
+(defgroup lsp-ui-imenu nil
+ "Display imenu entries."
+ :group 'tools
+ :group 'convenience
+ :group 'lsp-ui
+ :link '(custom-manual "(lsp-ui-imenu) Top")
+ :link '(info-link "(lsp-ui-imenu) Customizing"))
+
+(defcustom lsp-ui-imenu-enable t
+ "Whether or not to enable ‘lsp-ui-imenu’."
+ :type 'boolean
+ :group 'lsp-ui)
+
+(defcustom lsp-ui-imenu-kind-position 'top
+ "Where to show the entries kind."
+ :type '(choice (const :tag "Top" top)
+ (const :tag "Left" left))
+ :group 'lsp-ui-imenu)
+
+(defcustom lsp-ui-imenu-colors '("deep sky blue" "green3")
+ "Color list to cycle through for entry groups."
+ :type '(repeat color)
+ :group 'lsp-ui-imenu)
+
+(defcustom lsp-ui-imenu-window-width 0
+ "When not 0, don't fit window to buffer and use value as window-width."
+ :type 'number
+ :group 'lsp-ui-imenu)
+
+(defcustom lsp-ui-imenu-auto-refresh nil
+ "Automatically refresh imenu when certain conditions meet."
+ :type '(choice (const :tag "Enable" t)
+ (const :tag "Active only when after save" after-save)
+ (const :tag "Disable" nil))
+ :group 'lsp-ui-imenu)
+
+(defcustom lsp-ui-imenu-auto-refresh-delay 1.0
+ "Delay time to refresh imenu."
+ :type 'float
+ :group 'lsp-ui-imenu)
+
+(defcustom lsp-ui-imenu--custom-mode-line-format nil
+ "Custom mode line format to be used in `lsp-ui-menu-mode'."
+ :type 'sexp
+ :group 'lsp-ui-menu)
+
+(defconst lsp-ui-imenu--max-bars 8)
+
+(declare-function imenu--make-index-alist 'imenu)
+(declare-function imenu--subalist-p 'imenu)
+(defvar imenu--index-alist)
+
+(defvar-local lsp-ui-imenu--refresh-timer nil
+ "Auto refresh timer for imenu.")
+
+(defun lsp-ui-imenu--pad (s len bars depth color-index for-title is-last)
+ (let ((n (- len (length s))))
+ (apply #'concat
+ (make-string n ?\s)
+ (propertize s 'face `(:foreground ,(lsp-ui-imenu--get-color color-index)))
+ (let (bar-strings)
+ (dotimes (i depth)
+ (push
+ (propertize (lsp-ui-imenu--get-bar bars i depth for-title is-last)
+ 'face `(:foreground
+ ,(lsp-ui-imenu--get-color (+ color-index i))))
+ bar-strings))
+ (reverse bar-strings)))))
+
+(defun lsp-ui-imenu--get-bar (bars index depth for-title is-last)
+ (cond
+ ;; Exceeding maximum bars
+ ((>= index lsp-ui-imenu--max-bars) " ")
+ ;; No bar for this level
+ ((not (aref bars index)) " ")
+ ;; For the first level, the title is rendered differently, so leaf items are
+ ;; decorated with the full height bar regardless if it's the last item or
+ ;; not.
+ ((and (= depth 1) (not for-title)) " ┃ ")
+ ;; Full height bar for levels other than the rightmost one.
+ ((< (1+ index) depth) " ┃ ")
+ ;; The rightmost bar for the last item.
+ (is-last " â”— " )
+ ;; The rightmost bar for the title items other than the last one.
+ (for-title " ┣ ")
+ ;; The rightmost bar for the leaf items other than the last one.
+ (t " ┃ ")))
+
+(defun lsp-ui-imenu--get-color (index)
+ (nth (mod index (length lsp-ui-imenu-colors)) lsp-ui-imenu-colors))
+
+(defun lsp-ui-imenu--make-line (title index entry padding bars depth color-index is-last)
+ (let* ((prefix (if (and (= index 0) (eq lsp-ui-imenu-kind-position 'left)) title " "))
+ (text (concat (lsp-ui-imenu--pad prefix padding bars depth color-index nil is-last)
+ (propertize (car entry) 'face 'default)
+ "\n"))
+ (len (length text)))
+ (add-text-properties 0 len `(index ,index title ,title marker ,(cdr entry)
+ padding ,padding depth, depth)
+ text)
+ text))
+
+(defvar-local lsp-ui-imenu-ov nil
+ "Variable that holds overlay for imenu.")
+
+(defun lsp-ui-imenu--make-ov nil
+ "Make imenu overlay."
+ (or (and (overlayp lsp-ui-imenu-ov) lsp-ui-imenu-ov)
+ (setq lsp-ui-imenu-ov (make-overlay 1 1))))
+
+(defun lsp-ui-imenu--post-command nil
+ "Post command hook for imenu."
+ (when (eobp) (forward-line -1))
+ (lsp-ui-imenu--move-to-name-beginning)
+ (when (eq lsp-ui-imenu-kind-position 'left)
+ (save-excursion
+ (when (overlayp lsp-ui-imenu-ov)
+ (overlay-put lsp-ui-imenu-ov 'display nil))
+ (redisplay)
+ (goto-char (window-start))
+ (if (= (get-text-property (point) 'index) 0)
+ (when (overlayp lsp-ui-imenu-ov) (delete-overlay lsp-ui-imenu-ov))
+ (let* ((ov (lsp-ui-imenu--make-ov))
+ (padding (get-text-property (point) 'padding))
+ (title (get-text-property (point) 'title))
+ (text (buffer-substring (+ (line-beginning-position) padding) (line-end-position))))
+ (move-overlay ov (line-beginning-position) (line-end-position))
+ (overlay-put ov 'display `(string ,(concat (let ((n (- padding (length title))))
+ (propertize (concat (make-string n ?\s) title)))
+ text))))))))
+
+(defun lsp-ui-imenu--move-to-name-beginning ()
+ (-when-let* ((padding (get-char-property (point) 'padding))
+ (depth (get-char-property (point) 'depth)))
+ (goto-char (+ (* depth 3) (line-beginning-position) padding))))
+
+(defvar lsp-ui-imenu--origin nil)
+
+(defun lsp-ui-imenu--put-separator nil
+ (let ((ov (make-overlay (point) (point))))
+ (overlay-put ov 'after-string (propertize "\n" 'face '(:height 0.6)))))
+
+(defun lsp-ui-imenu--put-toplevel-title (title color-index)
+ (if (eq lsp-ui-imenu-kind-position 'top)
+ (let ((ov (make-overlay (point) (point)))
+ (color (lsp-ui-imenu--get-color color-index)))
+ (overlay-put
+ ov 'after-string
+ (concat (propertize "\n" 'face '(:height 0.6))
+ (propertize title 'face `(:foreground ,color))
+ "\n"
+ (propertize "\n" 'face '(:height 0.6)))))
+ ;; Left placement, title is put with the first sub item. Only put a separator here.
+ (lsp-ui-imenu--put-separator)))
+
+(defun lsp-ui-imenu--put-subtitle (title padding bars depth color-index is-last)
+ (let ((ov (make-overlay (point) (point)))
+ (title-color (lsp-ui-imenu--get-color (+ color-index depth))))
+ (overlay-put
+ ov 'after-string
+ (concat (lsp-ui-imenu--pad " " padding bars depth color-index t is-last)
+ (propertize title 'face `(:foreground ,title-color))
+ (propertize "\n" 'face '(:height 1))))))
+
+(defun lsp-ui-imenu--insert-items (title items padding bars depth color-index)
+ "Insert ITEMS for TITLE.
+
+PADDING is the length of whitespaces to the left of the first bar.
+
+BARS is a bool vector of length `lsp-ui-imenu--max-bars'. The ith
+value indicates whether the ith bar from the left is visible.
+
+DEPTH is the depth of the items in the index tree, starting from 0.
+
+COLOR-INDEX is the index of the color of the leftmost bar.
+
+Return the updated COLOR-INDEX."
+ (let ((len (length items)))
+ (--each-indexed items
+ (let ((is-last (= (1+ it-index) len)))
+ (if (imenu--subalist-p it)
+ (-let* (((sub-title . entries) it))
+ (if (= depth 0)
+ (lsp-ui-imenu--put-toplevel-title sub-title color-index)
+ (lsp-ui-imenu--put-subtitle sub-title padding bars depth color-index is-last))
+ (when (and is-last (> depth 0))
+ (aset bars (1- depth) nil))
+ (let ((lsp-ui-imenu-kind-position (if (> depth 0) 'top
+ lsp-ui-imenu-kind-position)))
+ (lsp-ui-imenu--insert-items sub-title
+ entries
+ padding
+ bars
+ (1+ depth)
+ color-index))
+ (when (and is-last (> depth 0))
+ (aset bars (1- depth) t))
+ (when (= depth 0)
+ (setq color-index (1+ color-index))))
+ (insert (lsp-ui-imenu--make-line title it-index it
+ padding bars depth color-index
+ is-last))))))
+ color-index)
+
+(defun lsp-ui-imenu--get-padding (items)
+ "Get imenu padding determined by `lsp-ui-imenu-kind-position'.
+ITEMS are used when the kind position is 'left."
+ (cl-case lsp-ui-imenu-kind-position
+ (top 1)
+ (left (--> (-filter 'imenu--subalist-p items)
+ (--map (length (car it)) it)
+ (-max (or it '(1)))))
+ (t (user-error "Invalid value for imenu's kind position: %s" lsp-ui-imenu-kind-position))))
+
+(defun lsp-ui-imenu--put-bit (bits offset)
+ (logior bits (lsh 1 offset)))
+
+(defun lsp-ui-imenu--clear-bit (bits offset)
+ (logand bits (lognot (lsh 1 offset))))
+
+(defvar lsp-ui-imenu-buffer-name "*lsp-ui-imenu*"
+ "Buffer name for imenu buffers.")
+
+(defun lsp-ui-imenu--refresh-content ()
+ "Refresh imenu content menu"
+ (let ((imenu-auto-rescan t))
+ (setq lsp-ui-imenu--origin (current-buffer))
+ (imenu--make-index-alist)
+ (let ((imenu-buffer (get-buffer-create lsp-ui-imenu-buffer-name))
+ (list imenu--index-alist))
+ (with-current-buffer imenu-buffer
+ (let* ((padding (lsp-ui-imenu--get-padding list))
+ (grouped-by-subs (-partition-by 'imenu--subalist-p list))
+ (color-index 0)
+ (bars (make-bool-vector lsp-ui-imenu--max-bars t))
+ (inhibit-read-only t))
+ (remove-overlays)
+ (erase-buffer)
+ (dolist (group grouped-by-subs)
+ (if (imenu--subalist-p (car group))
+ (setq color-index (lsp-ui-imenu--insert-items "" group padding bars 0 color-index))
+ (lsp-ui-imenu--put-separator)
+ (lsp-ui-imenu--insert-items "" group padding bars 1 color-index)
+ (setq color-index (1+ color-index))))
+ (lsp-ui-imenu-mode)
+ (when lsp-ui-imenu--custom-mode-line-format
+ (setq mode-line-format lsp-ui-imenu--custom-mode-line-format))
+ (goto-char (point-min))
+ (add-hook 'post-command-hook 'lsp-ui-imenu--post-command nil t))))))
+
+(defun lsp-ui-imenu nil
+ "Open ui-imenu in side window."
+ (interactive)
+ (lsp-ui-imenu-buffer-mode 1)
+ (setq lsp-ui-imenu--origin (current-buffer))
+ (imenu--make-index-alist)
+ (let ((imenu-buffer (get-buffer-create lsp-ui-imenu-buffer-name)))
+ (lsp-ui-imenu--refresh-content)
+ (let ((win (display-buffer-in-side-window imenu-buffer '((side . right)))))
+ (set-window-margins win 1)
+ (select-window win)
+ (set-window-start win 1)
+ (lsp-ui-imenu--move-to-name-beginning)
+ (set-window-dedicated-p win t)
+ ;; when `lsp-ui-imenu-window-width' is 0, fit window to buffer
+ (if (= lsp-ui-imenu-window-width 0)
+ (let ((fit-window-to-buffer-horizontally 'only))
+ (fit-window-to-buffer win)
+ (window-resize win 3 t))
+ (let ((x (- lsp-ui-imenu-window-width (window-width))))
+ (window-resize (selected-window) x t))))))
+
+(defun lsp-ui-imenu--kill nil
+ "Kill imenu window."
+ (interactive)
+ (lsp-ui-imenu-buffer-mode -1)
+ (kill-buffer-and-window))
+
+(defun lsp-ui-imenu--jump (direction)
+ (let ((current (get-text-property (point) 'title)))
+ (forward-line direction)
+ (while (and current
+ (not (= (line-number-at-pos) 1))
+ (equal current (get-text-property (point) 'title)))
+ (forward-line direction))))
+
+(defun lsp-ui-imenu--next-kind nil
+ "Jump to next kind of imenu."
+ (interactive)
+ (lsp-ui-imenu--jump 1))
+
+(defun lsp-ui-imenu--prev-kind nil
+ "Jump to previous kind of imenu."
+ (interactive)
+ (lsp-ui-imenu--jump -1)
+ (while (not (= (get-text-property (point) 'index) 0))
+ (forward-line -1)))
+
+(defun lsp-ui-imenu--visit nil
+ (interactive)
+ (let ((marker (get-text-property (point) 'marker)))
+ (select-window (get-buffer-window lsp-ui-imenu--origin))
+ (goto-char marker)
+ (pulse-momentary-highlight-one-line (point) 'next-error)))
+
+(defun lsp-ui-imenu--view nil
+ (interactive)
+ (let ((marker (get-text-property (point) 'marker)))
+ (with-selected-window (get-buffer-window lsp-ui-imenu--origin)
+ (goto-char marker)
+ (recenter)
+ (pulse-momentary-highlight-one-line (point) 'next-error))))
+
+(defvar lsp-ui-imenu-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "q") 'lsp-ui-imenu--kill)
+ (define-key map (kbd "r") 'lsp-ui-imenu--refresh)
+ (define-key map (kbd "<right>") 'lsp-ui-imenu--next-kind)
+ (define-key map (kbd "<left>") 'lsp-ui-imenu--prev-kind)
+ (define-key map (kbd "<return>") 'lsp-ui-imenu--view)
+ (define-key map (kbd "<M-return>") 'lsp-ui-imenu--visit)
+ (define-key map (kbd "RET") 'lsp-ui-imenu--view)
+ (define-key map (kbd "M-RET") 'lsp-ui-imenu--visit)
+ map)
+ "Keymap for ‘lsp-ui-peek-mode’.")
+
+(define-derived-mode lsp-ui-imenu-mode special-mode "lsp-ui-imenu"
+ "Mode showing imenu entries.")
+
+(defun lsp-ui-imenu--refresh ()
+ "Safe refresh imenu content."
+ (interactive)
+ (let ((imenu-buffer (get-buffer lsp-ui-imenu-buffer-name)))
+ (when imenu-buffer
+ (save-selected-window
+ (if (equal (current-buffer) imenu-buffer)
+ (select-window (get-buffer-window lsp-ui-imenu--origin))
+ (setq lsp-ui-imenu--origin (current-buffer)))
+ (lsp-ui-imenu--refresh-content)))))
+
+(defun lsp-ui-imenu--start-refresh (&rest _)
+ "Starts the auto refresh timer."
+ (lsp-ui-util-safe-kill-timer lsp-ui-imenu--refresh-timer)
+ (setq lsp-ui-imenu--refresh-timer
+ (run-with-idle-timer lsp-ui-imenu-auto-refresh-delay nil #'lsp-ui-imenu--refresh)))
+
+(defun lsp-ui-imenu-buffer--enable ()
+ "Enable `lsp-ui-imenu-buffer'."
+ (when lsp-ui-imenu-auto-refresh
+ (cl-case lsp-ui-imenu-auto-refresh
+ (after-save
+ (add-hook 'after-save-hook #'lsp-ui-imenu--start-refresh nil t))
+ (t
+ (add-hook 'after-change-functions #'lsp-ui-imenu--start-refresh nil t)
+ (add-hook 'after-save-hook #'lsp-ui-imenu--start-refresh nil t)))))
+
+(defun lsp-ui-imenu-buffer--disable ()
+ "Disable `lsp-ui-imenu-buffer'."
+ (when lsp-ui-imenu-auto-refresh
+ (cl-case lsp-ui-imenu-auto-refresh
+ (after-save
+ (remove-hook 'after-save-hook #'lsp-ui-imenu--start-refresh t))
+ (t
+ (remove-hook 'after-change-functions #'lsp-ui-imenu--start-refresh t)
+ (remove-hook 'after-save-hook #'lsp-ui-imenu--start-refresh t)))))
+
+(define-minor-mode lsp-ui-imenu-buffer-mode
+ "Minor mode 'lsp-ui-imenu-buffer-mode'."
+ :group lsp-ui-imenu
+ (if lsp-ui-imenu-buffer-mode (lsp-ui-imenu-buffer--enable) (lsp-ui-imenu-buffer--disable)))
+
+(provide 'lsp-ui-imenu)
+;;; lsp-ui-imenu.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-peek.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-peek.el
new file mode 100644
index 0000000..c73028c
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-peek.el
@@ -0,0 +1,754 @@
+;;; lsp-ui-peek.el --- Lsp-Ui-Peek -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Sebastien Chapuis
+
+;; Author: Sebastien Chapuis <sebastien@chapu.is>
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languagues, tools
+;; Version: 0.0.1
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; Load this file and execute `lsp-ui-peek-find-references'
+;; on a symbol to find its references
+;; or `lsp-ui-peek-find-definitions'.
+;; Type 'q' to close the window.
+;;
+
+;;; Code:
+
+(require 'lsp-protocol)
+(require 'lsp-mode)
+(require 'xref)
+(require 'dash)
+
+(defgroup lsp-ui-peek nil
+ "Improve version of xref with peek feature."
+ :group 'tools
+ :group 'convenience
+ :group 'lsp-ui
+ :link '(custom-manual "(lsp-ui-peek) Top")
+ :link '(info-link "(lsp-ui-peek) Customizing"))
+
+(defcustom lsp-ui-peek-enable t
+ "Whether or not to enable ‘lsp-ui-peek’."
+ :type 'boolean
+ :group 'lsp-ui)
+
+(defcustom lsp-ui-peek-show-directory t
+ "Whether or not to show the directory of files."
+ :type 'boolean
+ :safe t
+ :group 'lsp-ui-peek)
+
+(defcustom lsp-ui-peek-peek-height 20
+ "Height of the peek code."
+ :type 'integer
+ :group 'lsp-ui-peek)
+
+(defcustom lsp-ui-peek-list-width 50
+ "Width of the right panel."
+ :type 'integer
+ :group 'lsp-ui-peek)
+
+(defcustom lsp-ui-peek-fontify 'on-demand
+ "Whether to fontify chunks of code (use semantics colors).
+WARNING: 'always can heavily slow the processing when
+`lsp-ui-peek-expand-function' expands more than 1 file.
+It is recommended to keep the default value of `lsp-ui-peek-expand-function'
+when this variable is set to 'always."
+ :type '(choice (const :tag "Never" never)
+ (const :tag "On demand" on-demand)
+ (const :tag "Always" always))
+ :group 'lsp-ui-peek)
+
+(defcustom lsp-ui-peek-always-show nil
+ "Show the peek view even if there is only 1 cross reference.
+By default, the peek view isn't shown if there is 1 xref."
+ :type 'boolean
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-peek
+ '((((background light)) :background "light gray")
+ (t :background "#031A25"))
+ "Face used for the peek."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-list
+ '((((background light)) :background "light gray")
+ (t :background "#181818"))
+ "Face used to list references."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-filename
+ '((((background light)) :foreground "red")
+ (t :foreground "dark orange"))
+ "Face used for the filename's reference in the list."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-line-number
+ '((t :foreground "grey25"))
+ "Line number face."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-highlight
+ '((((background light)) :background "yellow"
+ :box (:line-width -1 :color "red"))
+ (t :background "white"
+ :foreground "black"
+ :distant-foreground "white"
+ :box (:line-width -1 :color "red")))
+ "Face used to highlight the reference/definition.
+Do not use box, underline or overline prop. If you want to use
+box, use a negative value for its width. Those properties deform
+the whole overlay."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-header
+ '((((background light)) :background "grey30" :foreground "white")
+ (t :background "white" :foreground "black"))
+ "Face used for the headers."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-footer
+ '((t :inherit lsp-ui-peek-header))
+ "Face used for the footers. Only the background of this face is used."
+ :group 'lsp-ui-peek)
+
+(defface lsp-ui-peek-selection
+ '((((background light)) :background "grey30" :foreground "white")
+ (t :background "white" :foreground "black"))
+ "Face used for the current selection.
+Do not use box, underline or overline prop. If you want to use
+box, use a negative value for its width. Those properties
+deform the whole overlay."
+ :group 'lsp-ui-peek)
+
+(defvar lsp-ui-peek-expand-function 'lsp-ui-peek--expand-buffer
+ "A function used to determinate which file(s) to expand in the list of xrefs.
+The function takes one parameter: a list of cons where the car is the
+filename and the cdr is the number of references in that file.
+It should returns a list of filenames to expand.
+WARNING: If you change this variable and expand more than 1 file, it is
+recommended to set `lsp-ui-peek-fontify' to 'never or 'on-demand, otherwise it
+will cause performances issues.")
+
+(defvar-local lsp-ui-peek--overlay nil)
+(defvar-local lsp-ui-peek--list nil)
+(defvar-local lsp-ui-peek--last-xref nil)
+(defvar-local lsp-ui-peek--selection 0)
+(defvar-local lsp-ui-peek--offset 0)
+(defvar-local lsp-ui-peek--size-list 0)
+(defvar-local lsp-ui-peek--win-start nil)
+(defvar-local lsp-ui-peek--method nil)
+(defvar-local lsp-ui-peek--deactivate-keymap-fn nil)
+
+(defvar lsp--peek-save-major-mode nil
+ "Stores the major mode for lsp ui peek.")
+
+(defvar lsp-ui-peek--jumps (make-hash-table)
+ "Hashtable which stores all jumps on a per window basis.")
+
+(defvar evil--jumps-window-jumps) ; defined in evil-jumps.el
+
+(defmacro lsp-ui-peek--with-evil-jumps (&rest body)
+ "Make `evil-jumps.el' commands work on `lsp-ui-peek--jumps'."
+ (declare (indent 1))
+ `(let ((evil--jumps-window-jumps lsp-ui-peek--jumps))
+ ,@body))
+
+(with-eval-after-load 'evil-jumps
+ ;; We need to jump through some hoops to prevent the byte-compiler from
+ ;; compiling this code. We can’t compile the code without requiring
+ ;; ‘evil-macros’.
+ (eval '(progn
+ (evil-define-motion lsp-ui-peek-jump-backward (count)
+ (lsp-ui-peek--with-evil-jumps
+ (evil--jump-backward count)
+ (run-hooks 'xref-after-return-hook)))
+ (evil-define-motion lsp-ui-peek-jump-forward (count)
+ (lsp-ui-peek--with-evil-jumps
+ (evil--jump-forward count)
+ (run-hooks 'xref-after-return-hook))))
+ t))
+
+(defmacro lsp-ui-peek--prop (prop &optional string)
+ `(get-text-property 0 ,prop (or ,string (lsp-ui-peek--get-text-selection) "")))
+
+(defmacro lsp-ui-peek--add-prop (prop &optional string)
+ `(let ((obj (or ,string (lsp-ui-peek--get-text-selection))))
+ (add-text-properties 0 (length obj) ,prop obj)
+ obj))
+
+(defun lsp-ui-peek--truncate (len s)
+ (if (> (string-width s) len)
+ (concat (truncate-string-to-width s (max (- len 2) 0)) "..")
+ s))
+
+(defun lsp-ui-peek--get-text-selection (&optional n)
+ (nth (or n lsp-ui-peek--selection)
+ (--remove (get-text-property 0 'lsp-ui-peek-hidden it) lsp-ui-peek--list)))
+
+(defun lsp-ui-peek--get-selection ()
+ (get-text-property 0 'lsp-ui-peek (or (lsp-ui-peek--get-text-selection) "")))
+
+(defun lsp-ui-peek--visual-index ()
+ (- lsp-ui-peek--selection lsp-ui-peek--offset))
+
+(defun lsp-ui-peek--make-line (index src)
+ (-let* (((s1 . s2) src)
+ (len-s1 (length s1))
+ (len-s2 (length s2))
+ (on-selection (= (1+ (lsp-ui-peek--visual-index)) index))
+ (face-left (if (= index 0) 'lsp-ui-peek-header 'lsp-ui-peek-peek))
+ (face-right (cond (on-selection 'lsp-ui-peek-selection)
+ ((= index 0) 'lsp-ui-peek-header)
+ (t 'lsp-ui-peek-list))))
+ (when on-selection
+ (setq s2 (copy-sequence s2))
+ (add-face-text-property 0 len-s2 face-right nil s2))
+ (unless (get-text-property 0 'lsp-ui-peek-faced s2)
+ (add-face-text-property 0 len-s2 face-right t s2)
+ (add-text-properties 0 len-s2 '(lsp-ui-peek-faced t) s2)
+ (add-face-text-property 0 len-s2 'default t s2))
+ (add-face-text-property 0 len-s1 face-left t s1)
+ (add-face-text-property 0 len-s1 'default t s1)
+ (concat
+ s1
+ (propertize "_" 'face face-left 'display `(space :align-to (- right-fringe ,(1+ lsp-ui-peek-list-width))))
+ " "
+ s2
+ (propertize "_" 'face face-right 'display `(space :align-to (- right-fringe 1)))
+ (propertize "\n" 'face face-right))))
+
+(defun lsp-ui-peek--adjust (width strings)
+ (-let* (((s1 . s2) strings))
+ (cons (lsp-ui-peek--truncate (- width (1+ lsp-ui-peek-list-width)) s1)
+ (lsp-ui-peek--truncate (- lsp-ui-peek-list-width 2) s2))))
+
+(defun lsp-ui-peek--make-footer ()
+ ;; Character-only terminals don't support characters of different height
+ (when (display-graphic-p)
+ (list
+ (concat
+ (propertize " "
+ 'face `(:background ,(face-background 'lsp-ui-peek-footer nil t) :height 1)
+ 'display `(space :align-to (- right-fringe ,(1+ lsp-ui-peek-list-width))))
+ (propertize " " 'face '(:height 1)
+ 'display `(space :align-to (- right-fringe ,lsp-ui-peek-list-width)))
+ (propertize " "
+ 'face `(:background ,(face-background 'lsp-ui-peek-footer nil t) :height 1)
+ 'display `(space :align-to (- right-fringe 0)))
+ (propertize "\n" 'face '(:height 1))
+ (propertize "\n" 'face '(:height 0.5))))))
+
+(defun lsp-ui-peek--peek-new (src1 src2)
+ (-let* ((win-width (- (window-text-width)
+ (if (bound-and-true-p display-line-numbers-mode)
+ (+ 2 (line-number-display-width))
+ 0)))
+ (string (-some--> (-zip-fill "" src1 src2)
+ (--map (lsp-ui-peek--adjust win-width it) it)
+ (-map-indexed 'lsp-ui-peek--make-line it)
+ (-concat it (lsp-ui-peek--make-footer))))
+ (next-line (line-beginning-position 2))
+ (ov (or (when (overlayp lsp-ui-peek--overlay) lsp-ui-peek--overlay)
+ (make-overlay next-line next-line))))
+ (setq lsp-ui-peek--overlay ov)
+ (overlay-put ov 'after-string (mapconcat 'identity string ""))
+ (overlay-put ov 'display-line-numbers-disable t)
+ (overlay-put ov 'window (get-buffer-window))))
+
+(defun lsp-ui-peek--expand-buffer (files)
+ (if (--any? (equal (car it) buffer-file-name) files)
+ (list buffer-file-name)
+ (list (caar files))))
+
+(defun lsp-ui-peek--expand (xrefs)
+ (let* ((to-expand (->> (--map (cons (plist-get it :file) (plist-get it :count)) xrefs)
+ (funcall lsp-ui-peek-expand-function)))
+ first)
+ (while (nth lsp-ui-peek--selection lsp-ui-peek--list)
+ (when (and (lsp-ui-peek--prop 'xrefs)
+ (member (lsp-ui-peek--prop 'file) to-expand))
+ (unless first
+ (setq first (1+ lsp-ui-peek--selection)))
+ (lsp-ui-peek--toggle-file t))
+ (setq lsp-ui-peek--selection (1+ lsp-ui-peek--selection)))
+ (setq lsp-ui-peek--selection (or first 0))
+ (lsp-ui-peek--recenter)))
+
+(defun lsp-ui-peek--show (xrefs)
+ "Create a window to list references/defintions.
+XREFS is a list of references/definitions."
+ (setq lsp-ui-peek--win-start (window-start)
+ lsp-ui-peek--selection 0
+ lsp-ui-peek--offset 0
+ lsp-ui-peek--size-list 0
+ lsp-ui-peek--list nil)
+ (when (eq (logand lsp-ui-peek-peek-height 1) 1)
+ (setq lsp-ui-peek-peek-height (1+ lsp-ui-peek-peek-height)))
+ (when (< (- (line-number-at-pos (window-end)) (line-number-at-pos))
+ (+ lsp-ui-peek-peek-height 3))
+ (recenter 15))
+ (setq xrefs (--sort (string< (plist-get it :file) (plist-get other :file)) xrefs))
+ (--each xrefs
+ (-let* (((&plist :file filename :xrefs xrefs :count count) it)
+ (len-str (number-to-string count)))
+ (setq lsp-ui-peek--size-list (+ lsp-ui-peek--size-list count))
+ (push (concat (propertize (if lsp-ui-peek-show-directory
+ (lsp-ui--workspace-path filename)
+ (file-name-nondirectory filename))
+ 'face 'lsp-ui-peek-filename
+ 'file filename
+ 'xrefs xrefs)
+ (propertize " " 'display `(space :align-to (- right-fringe ,(1+ (length len-str)))))
+ (propertize len-str 'face 'lsp-ui-peek-filename))
+ lsp-ui-peek--list)))
+ (setq lsp-ui-peek--list (nreverse lsp-ui-peek--list))
+ (lsp-ui-peek--expand xrefs)
+ (lsp-ui-peek--peek))
+
+(defun lsp-ui-peek--recenter ()
+ (let ((half-height (/ lsp-ui-peek-peek-height 2)))
+ (when (> lsp-ui-peek--selection half-height)
+ (setq lsp-ui-peek--offset (- lsp-ui-peek--selection (1- half-height))))))
+
+(defun lsp-ui-peek--fill (min-len list)
+ (let ((len (length list)))
+ (if (< len min-len)
+ (append list (-repeat (- min-len len) ""))
+ list)))
+
+(defun lsp-ui-peek--render (major string)
+ (with-temp-buffer
+ (insert string)
+ (delay-mode-hooks
+ (let ((inhibit-message t))
+ (funcall major))
+ (ignore-errors
+ (font-lock-ensure)))
+ (buffer-string)))
+
+(defun lsp-ui-peek--peek ()
+ "Show reference's chunk of code."
+ (-let* ((xref (lsp-ui-peek--get-selection))
+ ((&plist :file file :chunk chunk) (or xref lsp-ui-peek--last-xref))
+ (header (concat " " (lsp-ui--workspace-path file) "\n"))
+ (header2 (format " %s %s" lsp-ui-peek--size-list
+ (string-remove-prefix "workspace/" (string-remove-prefix "textDocument/" lsp-ui-peek--method))))
+ (ref-view (--> chunk
+ (subst-char-in-string ?\t ?\s it)
+ (concat header it)
+ (split-string it "\n")))
+ (list-refs (->> lsp-ui-peek--list
+ (--remove (lsp-ui-peek--prop 'lsp-ui-peek-hidden it))
+ (-drop lsp-ui-peek--offset)
+ (-take (1- lsp-ui-peek-peek-height))
+ (lsp-ui-peek--fill (1- lsp-ui-peek-peek-height))
+ (-concat (list header2)))))
+ (setq lsp-ui-peek--last-xref (or xref lsp-ui-peek--last-xref))
+ (lsp-ui-peek--peek-new ref-view list-refs)
+ (and (fboundp 'lsp-ui-doc--hide-frame)
+ (lsp-ui-doc--hide-frame))))
+
+(defun lsp-ui-peek--toggle-text-prop (s)
+ (let ((state (lsp-ui-peek--prop 'lsp-ui-peek-hidden s)))
+ (lsp-ui-peek--add-prop `(lsp-ui-peek-hidden ,(not state)) s)))
+
+(defun lsp-ui-peek--toggle-hidden (file)
+ (setq lsp-ui-peek--list
+ (--map-when (string= (plist-get (lsp-ui-peek--prop 'lsp-ui-peek it) :file) file)
+ (prog1 it (lsp-ui-peek--toggle-text-prop it))
+ lsp-ui-peek--list)))
+
+(defun lsp-ui-peek--remove-hidden (file)
+ (setq lsp-ui-peek--list
+ (--map-when (string= (plist-get (lsp-ui-peek--prop 'lsp-ui-peek it) :file) file)
+ (prog1 it (lsp-ui-peek--add-prop '(lsp-ui-peek-hidden nil) it))
+ lsp-ui-peek--list)))
+
+(defun lsp-ui-peek--make-ref-line (xref)
+ (-let* (((&plist :summary summary :line line :file file) xref)
+ (string (format "%-3s %s"
+ (propertize (number-to-string (1+ line))
+ 'face 'lsp-ui-peek-line-number)
+ (string-trim summary))))
+ (lsp-ui-peek--add-prop `(lsp-ui-peek ,xref file ,file) string)))
+
+(defun lsp-ui-peek--insert-xrefs (xrefs filename index)
+ (setq lsp-ui-peek--list (--> (lsp-ui-peek--get-xrefs-in-file (cons filename xrefs))
+ (-map 'lsp-ui-peek--make-ref-line it)
+ (-insert-at (1+ index) it lsp-ui-peek--list)
+ (-flatten it)))
+ (lsp-ui-peek--add-prop '(xrefs nil)))
+
+(defun lsp-ui-peek--toggle-file (&optional no-update)
+ (interactive)
+ (-if-let* ((xrefs (lsp-ui-peek--prop 'xrefs))
+ (filename (lsp-ui-peek--prop 'file))
+ (index (--find-index (equal (lsp-ui-peek--prop 'file it) filename)
+ lsp-ui-peek--list)))
+ (lsp-ui-peek--insert-xrefs xrefs filename index)
+ (let ((file (lsp-ui-peek--prop 'file)))
+ (lsp-ui-peek--toggle-hidden file)
+ (while (not (equal file (lsp-ui-peek--prop 'file)))
+ (lsp-ui-peek--select-prev t))))
+ (unless no-update
+ (lsp-ui-peek--peek)))
+
+(defun lsp-ui-peek--select (index)
+ (setq lsp-ui-peek--selection (+ lsp-ui-peek--selection index)))
+
+(defun lsp-ui-peek--select-next (&optional no-update)
+ (interactive)
+ (when (lsp-ui-peek--get-text-selection (1+ lsp-ui-peek--selection))
+ (lsp-ui-peek--select 1)
+ (while (> (lsp-ui-peek--visual-index) (- lsp-ui-peek-peek-height 2))
+ (setq lsp-ui-peek--offset (1+ lsp-ui-peek--offset)))
+ (unless no-update
+ (lsp-ui-peek--peek))))
+
+(defun lsp-ui-peek--select-prev (&optional no-update)
+ (interactive)
+ (when (> lsp-ui-peek--selection 0)
+ (lsp-ui-peek--select -1)
+ (while (< (lsp-ui-peek--visual-index) 0)
+ (setq lsp-ui-peek--offset (1- lsp-ui-peek--offset))))
+ (unless no-update
+ (lsp-ui-peek--peek)))
+
+(defun lsp-ui-peek--skip-refs (fn)
+ (let ((last-file (lsp-ui-peek--prop 'file))
+ last-selection)
+ (when (lsp-ui-peek--get-selection)
+ (while (and (equal (lsp-ui-peek--prop 'file) last-file)
+ (not (equal last-selection lsp-ui-peek--selection)))
+ (setq last-selection lsp-ui-peek--selection)
+ (funcall fn t)))))
+
+(defun lsp-ui-peek--select-prev-file ()
+ (interactive)
+ (if (not (lsp-ui-peek--get-selection))
+ (lsp-ui-peek--select-prev)
+ (lsp-ui-peek--skip-refs 'lsp-ui-peek--select-prev)
+ (when (lsp-ui-peek--get-selection)
+ (lsp-ui-peek--skip-refs 'lsp-ui-peek--select-prev)
+ (unless (= lsp-ui-peek--selection 0)
+ (lsp-ui-peek--select-next t))))
+ (if (lsp-ui-peek--prop 'xrefs)
+ (lsp-ui-peek--toggle-file)
+ (lsp-ui-peek--remove-hidden (lsp-ui-peek--prop 'file)))
+ (lsp-ui-peek--select-next t)
+ (lsp-ui-peek--recenter)
+ (lsp-ui-peek--peek))
+
+(defun lsp-ui-peek--select-next-file ()
+ (interactive)
+ (lsp-ui-peek--skip-refs 'lsp-ui-peek--select-next)
+ (if (lsp-ui-peek--prop 'xrefs)
+ (lsp-ui-peek--toggle-file)
+ (lsp-ui-peek--remove-hidden (lsp-ui-peek--prop 'file)))
+ (lsp-ui-peek--select-next t)
+ (lsp-ui-peek--recenter)
+ (lsp-ui-peek--peek))
+
+(defun lsp-ui-peek--peek-hide ()
+ "Hide the chunk of code and restore previous state."
+ (when (overlayp lsp-ui-peek--overlay)
+ (delete-overlay lsp-ui-peek--overlay))
+ (setq lsp-ui-peek--overlay nil
+ lsp-ui-peek--last-xref nil)
+ (when lsp-ui-peek--win-start
+ (set-window-start (get-buffer-window) lsp-ui-peek--win-start)))
+
+(defun lsp-ui-peek--deactivate-keymap ()
+ "Deactivate keymap."
+ (-when-let (fn lsp-ui-peek--deactivate-keymap-fn)
+ (setq lsp-ui-peek--deactivate-keymap-fn nil)
+ (funcall fn)))
+
+(defun lsp-ui-peek--goto-xref (&optional x other-window)
+ "Go to a reference/definition."
+ (interactive)
+ (-if-let (xref (or x (lsp-ui-peek--get-selection)))
+ (-let (((&plist :file file :line line :column column) xref)
+ (buffer (current-buffer)))
+ (if (not (file-readable-p file))
+ (user-error "File not readable: %s" file)
+ (setq lsp-ui-peek--win-start nil)
+ (lsp-ui-peek--abort)
+ (let ((marker (with-current-buffer
+ (or (get-file-buffer file)
+ (find-file-noselect file))
+ (save-restriction
+ (widen)
+ (save-excursion
+ ;; When we jump to a file with line/column unspecified,
+ ;; we do not want to move the point if the buffer exists.
+ ;; We interpret line=column=0 differently here.
+ (when (> (+ line column) 0)
+ (goto-char 1)
+ (forward-line line)
+ (forward-char column))
+ (point-marker)))))
+ (cur-buffer-workspaces (and (boundp 'lsp--buffer-workspaces) lsp--buffer-workspaces)))
+ (if other-window
+ (pop-to-buffer (marker-buffer marker) t)
+ (switch-to-buffer (marker-buffer marker)))
+ (with-current-buffer buffer
+ (lsp-ui-peek-mode -1))
+ (unless lsp--buffer-workspaces
+ (setq lsp--buffer-workspaces cur-buffer-workspaces)
+ (lsp-mode 1)
+ (dolist (workspace cur-buffer-workspaces)
+ (lsp--open-in-workspace workspace)))
+ (goto-char marker)
+ (run-hooks 'xref-after-jump-hook))))
+ (lsp-ui-peek--toggle-file)))
+
+(defun lsp-ui-peek--goto-xref-other-window ()
+ (interactive)
+ (lsp-ui-peek--goto-xref nil t))
+
+(defvar lsp-ui-peek-mode-map
+ (let ((map (make-sparse-keymap)))
+ (suppress-keymap map t)
+ (define-key map "\e\e\e" 'lsp-ui-peek--abort)
+ (define-key map "\C-g" 'lsp-ui-peek--abort)
+ (define-key map (kbd "M-n") 'lsp-ui-peek--select-next-file)
+ (define-key map (kbd "<right>") 'lsp-ui-peek--select-next-file)
+ (define-key map (kbd "M-p") 'lsp-ui-peek--select-prev-file)
+ (define-key map (kbd "<left>") 'lsp-ui-peek--select-prev-file)
+ (define-key map (kbd "C-n") 'lsp-ui-peek--select-next)
+ (define-key map (kbd "n") 'lsp-ui-peek--select-next)
+ (define-key map (kbd "<down>") 'lsp-ui-peek--select-next)
+ (define-key map (kbd "C-p") 'lsp-ui-peek--select-prev)
+ (define-key map (kbd "p") 'lsp-ui-peek--select-prev)
+ (define-key map (kbd "<up>") 'lsp-ui-peek--select-prev)
+ (define-key map (kbd "TAB") 'lsp-ui-peek--toggle-file)
+ (define-key map (kbd "q") 'lsp-ui-peek--abort)
+ (define-key map (kbd "RET") 'lsp-ui-peek--goto-xref)
+ (define-key map (kbd "M-RET") 'lsp-ui-peek--goto-xref-other-window)
+ map)
+ "Keymap for ‘lsp-ui-peek-mode’.")
+
+(defun lsp-ui-peek--disable ()
+ "Do not call this function, call `lsp-ui-peek--abort' instead."
+ (when (bound-and-true-p lsp-ui-peek-mode)
+ (lsp-ui-peek-mode -1)
+ (lsp-ui-peek--peek-hide)))
+
+(defun lsp-ui-peek--abort ()
+ "Abort peek."
+ (interactive)
+ ;; The timer fixes https://github.com/emacs-lsp/lsp-ui/issues/33
+ (run-with-idle-timer 0 nil 'lsp-ui-peek--disable))
+
+(define-minor-mode lsp-ui-peek-mode
+ "Mode for lsp-ui-peek."
+ :init-value nil
+ (if lsp-ui-peek-mode
+ (setq lsp-ui-peek--deactivate-keymap-fn (set-transient-map lsp-ui-peek-mode-map t 'lsp-ui-peek--abort))
+ (lsp-ui-peek--deactivate-keymap)
+ (lsp-ui-peek--peek-hide)))
+
+(defun lsp-ui-peek--find-xrefs (input method param)
+ "Find INPUT references.
+METHOD is ‘references’, ‘definitions’, `implementation` or a custom kind.
+PARAM is the request params."
+ (setq lsp-ui-peek--method method)
+ (let ((xrefs (lsp-ui-peek--get-references method param)))
+ (unless xrefs
+ (user-error "Not found for: %s" input))
+ (xref-push-marker-stack)
+ (when (featurep 'evil-jumps)
+ (lsp-ui-peek--with-evil-jumps (evil-set-jump)))
+ (if (and (not lsp-ui-peek-always-show)
+ (not (cdr xrefs))
+ (= (length (plist-get (car xrefs) :xrefs)) 1))
+ (let ((x (car (plist-get (car xrefs) :xrefs))))
+ (-if-let (uri (lsp:location-uri x))
+ (-let (((&Range :start (&Position :line :character)) (lsp:location-range x)))
+ (lsp-ui-peek--goto-xref `(:file ,(lsp--uri-to-path uri) :line ,line :column ,character)))
+ (-let (((&Range :start (&Position :line :character)) (or (lsp:location-link-target-selection-range x)
+ (lsp:location-link-target-range x))))
+ (lsp-ui-peek--goto-xref `(:file ,(lsp--uri-to-path (lsp:location-link-target-uri x)) :line ,line :column ,character)))))
+ (lsp-ui-peek-mode)
+ (lsp-ui-peek--show xrefs))))
+
+(defun lsp-ui-peek-find-references (&optional include-declaration extra)
+ "Find references to the IDENTIFIER at point."
+ (interactive)
+ (lsp-ui-peek--find-xrefs (symbol-at-point) "textDocument/references"
+ (append extra (lsp--make-reference-params nil include-declaration))))
+
+(defun lsp-ui-peek-find-definitions (&optional extra)
+ "Find definitions to the IDENTIFIER at point."
+ (interactive)
+ (lsp-ui-peek--find-xrefs (symbol-at-point) "textDocument/definition"
+ (append extra (lsp--text-document-position-params))))
+
+(defun lsp-ui-peek-find-implementation (&optional extra)
+ "Find implementation locations of the symbol at point."
+ (interactive)
+ (lsp-ui-peek--find-xrefs (symbol-at-point) "textDocument/implementation"
+ (append extra (lsp--text-document-position-params))))
+
+(defun lsp-ui-peek-find-workspace-symbol (pattern &optional extra)
+ "Find symbols in the worskpace.
+The symbols are found matching PATTERN."
+ (interactive (list (read-string "workspace/symbol: "
+ nil 'xref--read-pattern-history)))
+ (lsp-ui-peek--find-xrefs pattern "workspace/symbol"
+ (append extra (lsp-make-workspace-symbol-params :query pattern))))
+
+(defun lsp-ui-peek-find-custom (method &optional extra)
+ "Find custom references.
+KIND is a symbol to name the references (definition, reference, ..).
+REQUEST is the method string to send the the language server.
+EXTRA is a plist of extra parameters."
+ (lsp-ui-peek--find-xrefs (symbol-at-point) method
+ (append extra (lsp--text-document-position-params))))
+
+(defun lsp-ui-peek--extract-chunk-from-buffer (pos start end)
+ "Return the chunk of code pointed to by POS (a Position object) in the current buffer.
+START and END are delimiters."
+ (let* ((point (lsp--position-to-point pos))
+ (inhibit-field-text-motion t)
+ (line-start (1+ (- 1 (/ lsp-ui-peek-peek-height 2))))
+ (line-end (/ lsp-ui-peek-peek-height 2)))
+ (save-excursion
+ (goto-char point)
+ (let* ((before (buffer-substring (line-beginning-position line-start) (line-beginning-position)))
+ (line (buffer-substring (line-beginning-position) (line-end-position)))
+ (after (buffer-substring (line-end-position) (line-end-position line-end)))
+ (len (length line))
+ (chunk (concat before line after))
+ (start-in-chunk (length before)))
+
+ (when (eq lsp-ui-peek-fontify 'on-demand)
+ (setq chunk (lsp-ui-peek--render lsp--peek-save-major-mode chunk)))
+
+ (remove-text-properties (+ (min start len) start-in-chunk)
+ (+ (if (null end) len (min end len)) start-in-chunk) '(face nil)
+ chunk)
+
+ (add-face-text-property (+ (min start len) start-in-chunk)
+ (+ (if (null end) len (min end len)) start-in-chunk)
+ 'lsp-ui-peek-highlight t chunk)
+
+ `(,(substring chunk start-in-chunk (+ start-in-chunk len)) . ,chunk)))))
+
+(defun lsp-ui-peek--xref-make-item (filename loc)
+ "Return an item from FILENAME given a LOC.
+LOCATION can be either a LSP Location or SymbolInformation."
+ ;; TODO: Read more informations from SymbolInformation.
+ ;; For now, only the location is used.
+ (-let* ((loc (or (lsp:symbol-information-location loc) loc))
+ (range (or (lsp:location-range loc)
+ (lsp:location-link-target-selection-range loc)
+ (lsp:location-link-target-range loc)))
+ ((&Range :start pos-start :end pos-end) range)
+ ((&Position :line start-line :character start-col) pos-start)
+ ((&Position :line end-line :character end-col) pos-end)
+ ((line . chunk) (lsp-ui-peek--extract-chunk-from-buffer pos-start start-col
+ (when (= start-line end-line) end-col))))
+ (list :summary (or line filename)
+ :chunk (or chunk filename)
+ :file filename
+ :line start-line
+ :column start-col)))
+
+(defun lsp-ui-peek--fontify-buffer (filename)
+ (when (eq lsp-ui-peek-fontify 'always)
+ (unless buffer-file-name
+ (make-local-variable 'delay-mode-hooks)
+ (let ((buffer-file-name filename)
+ (enable-local-variables nil)
+ (inhibit-message t)
+ (delay-mode-hooks t))
+ (set-auto-mode)))
+ (font-lock-ensure)))
+
+(defun lsp-ui-peek--get-xrefs-in-file (file)
+ "Return all references that contain a file.
+FILE is a cons where its car is the filename and the cdr is a list of Locations
+within the file. We open and/or create the file/buffer only once for all
+references. The function returns a list of `ls-xref-item'."
+ (let* ((filename (car file))
+ (visiting (find-buffer-visiting filename))
+ (fn (lambda (loc) (lsp-ui-peek--xref-make-item filename loc))))
+ (setq lsp--peek-save-major-mode major-mode)
+ (cond
+ (visiting
+ (with-temp-buffer
+ (insert-buffer-substring-no-properties visiting)
+ (lsp-ui-peek--fontify-buffer filename)
+ (mapcar fn (cdr file))))
+ ((file-readable-p filename)
+ (with-temp-buffer
+ (insert-file-contents-literally filename)
+ (lsp-ui-peek--fontify-buffer filename)
+ (mapcar fn (cdr file))))
+ (t (user-error "Cannot read %s" filename)))))
+
+(defun lsp-ui-peek--get-xrefs-list (file)
+ "Return a list of xrefs in FILE."
+ (-let* (((filename . xrefs) file))
+ `(:file ,filename :xrefs ,xrefs :count ,(length xrefs))))
+
+(defun lsp-ui-peek--get-references (method params)
+ "Get all references/definitions for the symbol under point.
+Returns item(s)."
+ (-when-let* ((locs (lsp-request method params))
+ (locs (if (listp locs)
+ locs
+ (if (vectorp locs)
+ (append locs nil)
+ (list locs)))))
+ (-filter
+ (-lambda ((&plist :file))
+ (or (f-file? file)
+ (ignore
+ (lsp-log "The following file %s is missing, ignoring from the results."
+ file))))
+ (mapcar #'lsp-ui-peek--get-xrefs-list
+ (if (lsp:location-uri (car locs))
+ ;; Location[]
+ (--group-by (lsp--uri-to-path (lsp:location-uri it)) locs)
+ ;; LocationLink[]
+ (--group-by (lsp--uri-to-path (lsp:location-link-target-uri it)) locs))))))
+
+(defvar lsp-ui-mode-map)
+
+(defun lsp-ui-peek-enable (_enable)
+ (interactive)
+ (unless (bound-and-true-p lsp-ui-mode-map)
+ (user-error "Please load lsp-ui before trying to enable lsp-ui-peek")))
+
+;; lsp-ui.el loads lsp-ui-peek.el, so we can’t ‘require’ lsp-ui.
+;; FIXME: Remove this cyclic dependency.
+(declare-function lsp-ui--workspace-path "lsp-ui" (path))
+
+(declare-function evil-set-jump "ext:evil-jumps.el" (&optional pos))
+
+(provide 'lsp-ui-peek)
+;;; lsp-ui-peek.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-pkg.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-pkg.el
new file mode 100644
index 0000000..4b3ae0a
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-pkg.el
@@ -0,0 +1,15 @@
+(define-package "lsp-ui" "20210718.445" "UI modules for lsp-mode"
+ '((emacs "26.1")
+ (dash "2.18.0")
+ (lsp-mode "6.0")
+ (markdown-mode "2.3"))
+ :commit "f0e1bb9668da952e62e7a81058b0ebc8e0700a17" :authors
+ '(("Sebastien Chapuis <sebastien@chapu.is>, Fangrui Song" . "i@maskray.me"))
+ :maintainer
+ '("Sebastien Chapuis <sebastien@chapu.is>, Fangrui Song" . "i@maskray.me")
+ :keywords
+ '("languages" "tools")
+ :url "https://github.com/emacs-lsp/lsp-ui")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-sideline.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-sideline.el
new file mode 100644
index 0000000..d348f02
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-sideline.el
@@ -0,0 +1,768 @@
+;;; lsp-ui-sideline.el --- Lsp-Ui-Sideline -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Sebastien Chapuis
+
+;; Author: Sebastien Chapuis <sebastien@chapu.is>
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languages, tools
+;; Version: 6.2
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; Utility to show information for the current line
+
+;;; Code:
+
+(require 'lsp-ui-util)
+(require 'lsp-protocol)
+(require 'lsp-mode)
+(require 'flycheck nil 'noerror)
+(require 'dash)
+(require 'seq)
+(require 'subr-x)
+(require 'face-remap)
+
+(defvar flycheck-display-errors-function)
+(declare-function flycheck-overlay-errors-in "ext:flycheck.el")
+(declare-function flycheck-error-format-message-and-id "ext:flycheck.el")
+(declare-function flycheck-error-level "ext:flycheck.el")
+
+(defgroup lsp-ui-sideline nil
+ "Display information for the current line."
+ :group 'tools
+ :group 'convenience
+ :group 'lsp-ui
+ :link '(custom-manual "(lsp-ui-sideline) Top")
+ :link '(info-link "(lsp-ui-sideline) Customizing"))
+
+(defcustom lsp-ui-sideline-enable t
+ "Whether or not to enable ‘lsp-ui-sideline’."
+ :type 'boolean
+ :group 'lsp-ui)
+
+(defcustom lsp-ui-sideline-ignore-duplicate nil
+ "Ignore duplicates when there is a same symbol with the same contents."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-show-symbol t
+ "When t, show the symbol name on the right of the information."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-show-hover nil
+ "Whether to show hover messages in sideline."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-show-diagnostics t
+ "Whether to show diagnostics messages in sideline."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-show-code-actions t
+ "Whether to show code actions in sideline."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-update-mode 'point
+ "Define the mode for updating sideline actions.
+
+When set to `line' the actions will be updated when user
+changes current line otherwise the actions will be updated
+when user changes current point."
+ :type '(choice (const line)
+ (const point))
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-delay 0.2
+ "Number of seconds to wait before showing sideline."
+ :type 'number
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-diagnostic-max-lines 1
+ "Maximum number of lines to show of diagnostics in sideline."
+ :type 'integer
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-diagnostic-max-line-length 100
+ "Maximum line length of diagnostics in sideline."
+ :type 'integer
+ :group 'lsp-ui-sideline)
+
+(defconst lsp-ui-sideline-actions-icon-default
+ (and (bound-and-true-p lsp-ui-resources-dir)
+ (image-type-available-p 'png)
+ (expand-file-name "lightbulb.png" lsp-ui-resources-dir)))
+
+;; TODO: Set the default actions to `nil' temporarily due to image
+;; scale issue on Emacs version 26.3 or below.
+;;
+;; See #573
+(defcustom lsp-ui-sideline-actions-icon nil
+ "Image file for actions. It must be a png file."
+ :type '(choice file (const :tag "Disable" nil))
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-wait-for-all-symbols t
+ "Wait for all symbols before displaying info in sideline."
+ :type 'boolean
+ :group 'lsp-ui-sideline)
+
+(defcustom lsp-ui-sideline-actions-kind-regex "quickfix.*\\|refactor.*"
+ "Regex for the code actions kinds to show in the sideline."
+ :type 'string
+ :group 'lsp-ui-sideline)
+
+(defvar lsp-ui-sideline-code-actions-prefix ""
+ "Prefix to insert before the code action title.
+This can be used to insert, for example, an unicode character: 💡")
+
+(defvar-local lsp-ui-sideline--ovs nil
+ "Overlays used by `lsp-ui-sideline'.")
+
+(defvar-local lsp-ui-sideline--occupied-lines nil
+ "List of lines occupied by an overlay of `lsp-ui-sideline'.")
+
+(defvar-local lsp-ui-sideline--first-line-pushed nil
+ "Record weather if we display sideline in the first line.
+
+If we do, then sideline will always look downward instead of the upward
+direction.
+
+This prevent sideline displays below than the first line, which it will cause
+weird looking user interface.")
+
+(defvar-local lsp-ui-sideline--tag nil
+ "Tag marking where the last operation was based.
+It is used to know when the cursor has changed its line or point.")
+
+(defvar-local lsp-ui-sideline--last-width nil
+ "Value of window's width on the last operation.
+It is used to know when the window has changed of width.")
+
+(defvar-local lsp-ui-sideline--last-line-number nil
+ "Line number on the last operation.
+Used to avoid calling `line-number-at-pos' when we're on the same line.")
+
+(defvar-local lsp-ui-sideline--timer nil)
+
+(defvar-local lsp-ui-sideline--code-actions nil
+ "Holds the latest code actions.")
+
+(defvar-local lsp-ui-sideline--cached-infos nil
+ "Cache of rendered line when `lsp-ui-sideline-wait-for-all-symbols'
+is nil. Used to not re-render the same line multiple times.")
+
+(defface lsp-ui-sideline-symbol
+ '((t :foreground "grey"
+ :box (:line-width -1 :color "grey")
+ :height 0.99))
+ "Face used to highlight symbols."
+ :group 'lsp-ui-sideline)
+
+(defface lsp-ui-sideline-current-symbol
+ '((((background light))
+ :foreground "black"
+ :weight ultra-bold
+ :box (:line-width -1 :color "black")
+ :height 0.99)
+ (t :foreground "white"
+ :weight ultra-bold
+ :box (:line-width -1 :color "white")
+ :height 0.99))
+ "Face used to highlight the symbol on point."
+ :group 'lsp-ui-sideline)
+
+(defface lsp-ui-sideline-code-action
+ '((((background light)) :foreground "DarkOrange")
+ (t :foreground "yellow"))
+ "Face used to highlight code action text."
+ :group 'lsp-ui-sideline)
+
+(defface lsp-ui-sideline-symbol-info
+ '((t :slant italic :height 0.99))
+ "Face used to highlight the symbols informations (LSP hover)."
+ :group 'lsp-ui-sideline)
+
+(defface lsp-ui-sideline-global
+ '((t))
+ "Face which apply to all overlays.
+This face have a low priority over the others."
+ :group 'lsp-ui-sideline)
+
+(defun lsp-ui-sideline--first-line-p (pos)
+ "Return non-nil if POS is on the first line."
+ (when (integerp pos)
+ (save-excursion (goto-char 1) (forward-line 1) (> (point) pos))))
+
+(defun lsp-ui-sideline--calc-space (win-width str-len index)
+ "Calculate whether there is enough space on line.
+If there is enough space, it returns the point of the last
+character on the line.
+
+WIN-WIDTH is the window width.
+STR-LEN is the string size.
+INDEX is the line number (relative to the current line)."
+ (let ((eol (line-end-position index)))
+ (unless (member eol lsp-ui-sideline--occupied-lines)
+ (save-excursion
+ (goto-char eol)
+ (end-of-line)
+ (when (>= (- win-width (current-column)) str-len)
+ eol)))))
+
+(defun lsp-ui-sideline--find-line (str-len bol eol &optional up offset)
+ "Find a line where the string can be inserted.
+
+It loops on the nexts lines to find enough space. Returns the point
+of the last character on the line.
+
+Argument STR-LEN is the string size.
+Argument BOL and EOL are beginning and ending of the user point line.
+If optional argument UP is non-nil, it loops on the previous lines.
+If optional argument OFFSET is non-nil, it starts search OFFSET lines
+from user point line."
+ (let ((win-width (lsp-ui-sideline--window-width))
+ (inhibit-field-text-motion t)
+ (index (if (null offset) 1 offset))
+ pos)
+ (while (and (null pos) (<= (abs index) 30))
+ (setq index (if up (1- index) (1+ index)))
+ (setq pos (lsp-ui-sideline--calc-space win-width str-len index)))
+ (if (and up (or (null pos) (and (<= pos 1) lsp-ui-sideline--first-line-pushed)))
+ (lsp-ui-sideline--find-line str-len bol eol nil offset)
+ (when (and (null lsp-ui-sideline--first-line-pushed)
+ (lsp-ui-sideline--first-line-p pos))
+ (setq lsp-ui-sideline--first-line-pushed t)) ; mark first line push
+ (and pos (or (> pos eol) (< pos bol))
+ (push pos lsp-ui-sideline--occupied-lines)
+ (list pos (1- index))))))
+
+(defun lsp-ui-sideline--delete-ov ()
+ "Delete overlays."
+ (seq-do 'delete-overlay lsp-ui-sideline--ovs)
+ (setq lsp-ui-sideline--tag nil
+ lsp-ui-sideline--cached-infos nil
+ lsp-ui-sideline--occupied-lines nil
+ lsp-ui-sideline--first-line-pushed (lsp-ui-sideline--first-line-p (point))
+ lsp-ui-sideline--ovs nil))
+
+(defun lsp-ui-sideline--extract-info (contents)
+ "Extract the line to print from CONTENTS.
+CONTENTS can be differents type of values:
+MarkedString | MarkedString[] | MarkupContent (as defined in the LSP).
+We prioritize string with a language (which is probably a type or a
+function signature)."
+ (when contents
+ (cond
+ ((lsp-marked-string? contents) contents)
+ ((vectorp contents)
+ (seq-find (lambda (it) (and (lsp-marked-string? it)
+ (lsp-get-renderer (lsp:marked-string-language it))))
+ contents))
+ ((lsp-markup-content? contents) contents))))
+
+(defun lsp-ui-sideline--format-info (marked-string win-width)
+ "Format MARKED-STRING.
+If the string has a language, we fontify it with the function provided
+by `lsp-mode'.
+MARKED-STRING is the string returned by `lsp-ui-sideline--extract-info'."
+ (when (and marked-string (or (lsp-marked-string? marked-string) (lsp-markup-content? marked-string)))
+ (setq marked-string (lsp--render-element marked-string))
+ (add-face-text-property 0 (length marked-string) 'lsp-ui-sideline-symbol-info nil marked-string)
+ (add-face-text-property 0 (length marked-string) 'default t marked-string)
+ (->> (if (> (length marked-string) (/ win-width 2))
+ (car (split-string (string-trim-left marked-string) "[\r\n]+"))
+ marked-string)
+ (replace-regexp-in-string "[\n\r\t ]+" " "))))
+
+(defun lsp-ui-sideline--align (&rest lengths)
+ "Align sideline string by LENGTHS from the right of the window."
+ (+ (apply '+ lengths)
+ (if (display-graphic-p) 1 2)))
+
+(defun lsp-ui-sideline--compute-height nil
+ "Return a fixed size for text in sideline."
+ (if (null text-scale-mode-remapping)
+ '(height 1)
+ ;; Readjust height when text-scale-mode is used
+ (list 'height
+ (/ 1 (or (plist-get (cdr text-scale-mode-remapping) :height)
+ 1)))))
+
+(defun lsp-ui-sideline--make-display-string (info symbol current)
+ "Make final string to display in buffer.
+INFO is the information to display.
+SYMBOL is the symbol associated with the info.
+CURRENT is non-nil when the point is on the symbol."
+ (let* ((face (if current 'lsp-ui-sideline-current-symbol 'lsp-ui-sideline-symbol))
+ (str (if lsp-ui-sideline-show-symbol
+ (concat info " " (propertize (concat " " symbol " ") 'face face))
+ info))
+ (len (length str))
+ (margin (lsp-ui-sideline--margin-width)))
+ (add-face-text-property 0 len 'lsp-ui-sideline-global nil str)
+ (concat
+ (propertize " " 'display `(space :align-to (- right-fringe ,(lsp-ui-sideline--align len margin))))
+ (propertize str 'display (lsp-ui-sideline--compute-height)))))
+
+(defun lsp-ui-sideline--check-duplicate (symbol info)
+ "Check if there's already a SYMBOL containing INFO, unless `lsp-ui-sideline-ignore-duplicate'
+is set to t."
+ (not (when lsp-ui-sideline-ignore-duplicate
+ (--any (and (string= (overlay-get it 'symbol) symbol)
+ (string= (overlay-get it 'info) info))
+ lsp-ui-sideline--ovs))))
+
+(defun lsp-ui-sideline--margin-width ()
+ (+ (if fringes-outside-margins right-margin-width 0)
+ (or (and (boundp 'fringe-mode)
+ (consp fringe-mode)
+ (or (equal (car fringe-mode) 0)
+ (equal (cdr fringe-mode) 0))
+ 1)
+ (and (boundp 'fringe-mode) (equal fringe-mode 0) 1)
+ 0)
+ (let ((win-fringes (window-fringes)))
+ (if (or (equal (car win-fringes) 0)
+ (equal (cadr win-fringes) 0))
+ 2
+ 0))
+ (if (< emacs-major-version 27)
+ ;; This was necessary with emacs < 27, recent versions take
+ ;; into account the display-line width with :align-to
+ (lsp-ui-util-line-number-display-width)
+ 0)
+ (if (or
+ (bound-and-true-p whitespace-mode)
+ (bound-and-true-p global-whitespace-mode))
+ 1
+ 0)))
+
+(defun lsp-ui-sideline--window-width ()
+ (- (min (window-text-width) (window-body-width))
+ (lsp-ui-sideline--margin-width)
+ (or (and (>= emacs-major-version 27)
+ ;; We still need this number when calculating available space
+ ;; even with emacs >= 27
+ (lsp-ui-util-line-number-display-width))
+ 0)))
+
+(defun lsp-ui-sideline--valid-tag-p (tag mode)
+ (when tag
+ (-let ((inhibit-field-text-motion t)
+ ((p bol _eol buffer) tag))
+ (when (and (= bol (line-beginning-position))
+ (eq buffer (current-buffer)))
+ (pcase mode
+ ('point (eq p (point)))
+ ('line t) ;; For 'line only bol is relevant
+ (_ (error "Wrong tag mode")))))))
+
+(defun lsp-ui-sideline--display-all-info (list-infos tag bol eol)
+ (when (and (lsp-ui-sideline--valid-tag-p tag 'line)
+ (not (lsp-ui-sideline--stop-p)))
+ (let ((inhibit-modification-hooks t)
+ (win-width (window-body-width))
+ ;; sort by bounds
+ (list-infos (--sort (< (caadr it) (caadr other)) list-infos)))
+ (lsp-ui-sideline--delete-kind 'info)
+ (--each list-infos
+ (-let (((symbol bounds info) it))
+ (lsp-ui-sideline--push-info win-width symbol bounds info bol eol))))))
+
+(defun lsp-ui-sideline--push-info (win-width symbol bounds info bol eol)
+ (let* ((markdown-hr-display-char nil)
+ (info (or (alist-get info lsp-ui-sideline--cached-infos)
+ (-some--> (lsp:hover-contents info)
+ (lsp-ui-sideline--extract-info it)
+ (lsp-ui-sideline--format-info it win-width)
+ (progn (push (cons info it) lsp-ui-sideline--cached-infos) it))))
+ (current (and (>= (point) (car bounds)) (<= (point) (cdr bounds)))))
+ (when (and (> (length info) 0)
+ (lsp-ui-sideline--check-duplicate symbol info))
+ (let* ((final-string (lsp-ui-sideline--make-display-string info symbol current))
+ (pos-ov (lsp-ui-sideline--find-line (length final-string) bol eol))
+ (ov (when pos-ov (make-overlay (car pos-ov) (car pos-ov)))))
+ (when pos-ov
+ (overlay-put ov 'info info)
+ (overlay-put ov 'symbol symbol)
+ (overlay-put ov 'bounds bounds)
+ (overlay-put ov 'current current)
+ (overlay-put ov 'after-string final-string)
+ (overlay-put ov 'before-string " ")
+ (overlay-put ov 'window (get-buffer-window))
+ (overlay-put ov 'kind 'info)
+ (overlay-put ov 'position (car pos-ov))
+ (push ov lsp-ui-sideline--ovs))))))
+
+(defun lsp-ui-sideline--toggle-current (ov current)
+ "Toggle the OV face according to CURRENT."
+ (let* ((info (overlay-get ov 'info))
+ (symbol (overlay-get ov 'symbol))
+ (string (lsp-ui-sideline--make-display-string info symbol current)))
+ (overlay-put ov 'current current)
+ (overlay-put ov 'after-string string)))
+
+(defun lsp-ui-sideline--highlight-current (point)
+ "Update the symbol's face according to POINT."
+ (dolist (ov lsp-ui-sideline--ovs)
+ (let* ((bounds (overlay-get ov 'bounds))
+ (start (car bounds))
+ (end (cdr bounds)))
+ (if (and bounds (>= point start) (<= point end))
+ (unless (overlay-get ov 'current)
+ (lsp-ui-sideline--toggle-current ov t))
+ (when (overlay-get ov 'current)
+ (lsp-ui-sideline--toggle-current ov nil))))))
+
+(defun lsp-ui-sideline--split-long-lines (lines)
+ "Fill LINES so that they are not longer than `lsp-ui-sideline-diagnostic-max-line-length' characters."
+ (cl-mapcan (lambda (line)
+ (if (< (length line) lsp-ui-sideline-diagnostic-max-line-length)
+ (list line)
+ (with-temp-buffer
+ (let ((fill-column lsp-ui-sideline-diagnostic-max-line-length))
+ (insert line)
+ (fill-region (point-min) (point-max))
+ (split-string (buffer-string) "\n")))))
+ lines))
+
+(defun lsp-ui-sideline--diagnostics (buffer bol eol)
+ "Show diagnostics belonging to the current line.
+Loop over flycheck errors with `flycheck-overlay-errors-in'.
+Find appropriate position for sideline overlays with `lsp-ui-sideline--find-line'.
+Push sideline overlays on `lsp-ui-sideline--ovs'."
+ (when (and (bound-and-true-p flycheck-mode)
+ (bound-and-true-p lsp-ui-sideline-mode)
+ lsp-ui-sideline-show-diagnostics
+ (eq (current-buffer) buffer))
+ (lsp-ui-sideline--delete-kind 'diagnostics)
+ (dolist (e (flycheck-overlay-errors-in bol (1+ eol)))
+ (let* ((lines (--> (flycheck-error-format-message-and-id e)
+ (split-string it "\n")
+ (lsp-ui-sideline--split-long-lines it)))
+ (display-lines (butlast lines (- (length lines) lsp-ui-sideline-diagnostic-max-lines)))
+ (offset 1))
+ (dolist (line (nreverse display-lines))
+ (let* ((msg (string-trim (replace-regexp-in-string "[\t ]+" " " line)))
+ (msg (replace-regexp-in-string " " " " msg))
+ (len (length msg))
+ (level (flycheck-error-level e))
+ (face (if (eq level 'info) 'success level))
+ (margin (lsp-ui-sideline--margin-width))
+ (msg (progn (add-face-text-property 0 len 'lsp-ui-sideline-global nil msg)
+ (add-face-text-property 0 len face nil msg)
+ msg))
+ (string (concat (propertize " " 'display `(space :align-to (- right-fringe ,(lsp-ui-sideline--align len margin))))
+ (propertize msg 'display (lsp-ui-sideline--compute-height))))
+ (pos-ov (lsp-ui-sideline--find-line len bol eol t offset))
+ (ov (and pos-ov (make-overlay (car pos-ov) (car pos-ov)))))
+ (when pos-ov
+ (setq offset (1+ (car (cdr pos-ov))))
+ (overlay-put ov 'after-string string)
+ (overlay-put ov 'kind 'diagnostics)
+ (overlay-put ov 'before-string " ")
+ (overlay-put ov 'position (car pos-ov))
+ (push ov lsp-ui-sideline--ovs))))))))
+
+(defun lsp-ui-sideline-apply-code-actions nil
+ "Choose and apply code action(s) on the current line."
+ (interactive)
+ (unless lsp-ui-sideline--code-actions
+ (user-error "No code actions on the current line"))
+ (lsp-execute-code-action (lsp--select-action lsp-ui-sideline--code-actions)))
+
+(defun lsp-ui-sideline-set-default-icon ()
+ "Set default icon for sideline actions."
+ (setq lsp-ui-sideline-actions-icon lsp-ui-sideline-actions-icon-default))
+
+(defun lsp-ui-sideline--scale-lightbulb (height)
+ "Scale the lightbulb image to character height.
+
+Argument HEIGHT is an actual image height in pixel."
+ (--> (- (frame-char-height) 1)
+ (/ (float it) height)))
+
+(defun lsp-ui-sideline--code-actions-make-image nil
+ (let ((is-default (equal lsp-ui-sideline-actions-icon lsp-ui-sideline-actions-icon-default)))
+ (--> `(image :type png :file ,lsp-ui-sideline-actions-icon :ascent center)
+ (append it `(:scale ,(->> (cond (is-default 128)
+ ((fboundp 'image-size) (cdr (image-size it t)))
+ (t (error "Function image-size undefined. Use default icon")))
+ (lsp-ui-sideline--scale-lightbulb)))))))
+
+(defun lsp-ui-sideline--code-actions-image nil
+ (when lsp-ui-sideline-actions-icon
+ (with-demoted-errors "[lsp-ui-sideline]: Error with actions icon: %s"
+ (concat
+ (propertize " " 'display (lsp-ui-sideline--code-actions-make-image))
+ (propertize " " 'display '(space :width 0.3))))))
+
+(defun lsp-ui-sideline--code-actions (actions bol eol)
+ "Show code ACTIONS."
+ (let ((inhibit-modification-hooks t))
+ (when lsp-ui-sideline-actions-kind-regex
+ (setq actions (seq-filter (-lambda ((&CodeAction :kind?))
+ (or (not kind?)
+ (s-match lsp-ui-sideline-actions-kind-regex kind?)))
+ actions)))
+ (setq lsp-ui-sideline--code-actions actions)
+ (lsp-ui-sideline--delete-kind 'actions)
+ (seq-doseq (action actions)
+ (-let* ((title (->> (lsp:code-action-title action)
+ (replace-regexp-in-string "[\n\t ]+" " ")
+ (replace-regexp-in-string " " " ")
+ (concat (unless lsp-ui-sideline-actions-icon
+ lsp-ui-sideline-code-actions-prefix))))
+ (image (lsp-ui-sideline--code-actions-image))
+ (margin (lsp-ui-sideline--margin-width))
+ (keymap (let ((map (make-sparse-keymap)))
+ (define-key map [down-mouse-1] (lambda () (interactive)
+ (save-excursion
+ (lsp-execute-code-action action))))
+ map))
+ (len (length title))
+ (title (progn (add-face-text-property 0 len 'lsp-ui-sideline-global nil title)
+ (add-face-text-property 0 len 'lsp-ui-sideline-code-action nil title)
+ (add-text-properties 0 len `(keymap ,keymap mouse-face highlight) title)
+ title))
+ (string (concat (propertize " " 'display `(space :align-to (- right-fringe ,(lsp-ui-sideline--align (+ len (length image)) margin))))
+ image
+ (propertize title 'display (lsp-ui-sideline--compute-height))))
+ (pos-ov (lsp-ui-sideline--find-line (+ 1 (length title) (length image)) bol eol t))
+ (ov (and pos-ov (make-overlay (car pos-ov) (car pos-ov)))))
+ (when pos-ov
+ (overlay-put ov 'after-string string)
+ (overlay-put ov 'before-string " ")
+ (overlay-put ov 'kind 'actions)
+ (overlay-put ov 'position (car pos-ov))
+ (push ov lsp-ui-sideline--ovs))))))
+
+(defun lsp-ui-sideline--calculate-tag nil
+ "Calculate the tag used to determine whether to update sideline information."
+ (let ((inhibit-field-text-motion t))
+ (list (point) (line-beginning-position) (line-end-position) (current-buffer))))
+
+(defun lsp-ui-sideline--delete-kind (kind)
+ (->> (--remove
+ (when (eq (overlay-get it 'kind) kind)
+ (--> (overlay-get it 'position)
+ (remq it lsp-ui-sideline--occupied-lines)
+ (setq lsp-ui-sideline--occupied-lines it))
+ (delete-overlay it)
+ t)
+ lsp-ui-sideline--ovs)
+ (setq lsp-ui-sideline--ovs)))
+
+(defvar-local lsp-ui-sideline--last-tick-info nil)
+(defvar-local lsp-ui-sideline--previous-line nil)
+
+(defun lsp-ui-sideline--get-line (bol eol)
+ (buffer-substring-no-properties bol eol))
+
+(defun lsp-ui-sideline--line-diags (line)
+ (->> (--filter
+ (let ((range (lsp-get it :range)))
+ (or (-some-> range (lsp-get :start) (lsp-get :line) (= line))
+ (-some-> range (lsp-get :end) (lsp-get :line) (= line))))
+ (lsp--get-buffer-diagnostics))
+ (apply 'vector)))
+
+(defun lsp-ui-sideline--run (&optional buffer bol eol this-line)
+ "Show information (flycheck + lsp).
+It loops on the symbols of the current line and requests information
+from the language server."
+ (when buffer-file-name
+ (let* ((inhibit-field-text-motion t)
+ (tag (lsp-ui-sideline--calculate-tag))
+ (eol (or eol (nth 2 tag)))
+ (bol (or bol (nth 1 tag)))
+ (this-tick (buffer-modified-tick))
+ (line-changed (not (lsp-ui-sideline--valid-tag-p lsp-ui-sideline--tag 'line)))
+ (line-widen (or (and (not line-changed) lsp-ui-sideline--last-line-number)
+ (and (buffer-narrowed-p) (save-restriction (widen) (line-number-at-pos)))
+ (line-number-at-pos)))
+ (new-tick (unless line-changed (not (equal this-tick lsp-ui-sideline--last-tick-info))))
+ (this-line (or this-line (lsp-ui-sideline--get-line bol eol)))
+ (line-modified (and new-tick (not (equal this-line lsp-ui-sideline--previous-line))))
+ (doc-id (lsp--text-document-identifier))
+ (inhibit-modification-hooks t)
+ symbols)
+ (setq lsp-ui-sideline--tag tag
+ lsp-ui-sideline--last-line-number line-widen
+ lsp-ui-sideline--last-width (window-text-width))
+ (when (and line-changed lsp-ui-sideline-show-diagnostics)
+ (lsp-ui-sideline--diagnostics buffer bol eol))
+ (when (and lsp-ui-sideline-show-code-actions
+ (or (lsp--capability "codeActionProvider")
+ (lsp--registered-capability "textDocument/codeAction")))
+ (lsp-request-async
+ "textDocument/codeAction"
+ (-let (((start . end) (if (eq lsp-ui-sideline-update-mode 'line)
+ (cons 0 (- eol bol))
+ (--> (- (point) bol) (cons it it)))))
+ (list :textDocument doc-id
+ :range (list :start (list :line (1- line-widen) :character start)
+ :end (list :line (1- line-widen) :character end))
+ :context (list :diagnostics (lsp-ui-sideline--line-diags (1- line-widen)))))
+ (lambda (actions)
+ (when (eq (current-buffer) buffer)
+ (lsp-ui-sideline--code-actions actions bol eol)))
+ :mode 'tick
+ :error-handler
+ (lambda (&rest _)
+ (lsp-ui-sideline--delete-kind 'actions))
+ :cancel-token :lsp-ui-code-actions))
+ ;; Go through all symbols and request hover information. Note that the symbols are
+ ;; traversed backwards as `forward-symbol' with a positive argument will jump just past the
+ ;; current symbol. By going from the end of the line towards the front, point will be placed
+ ;; at the beginning of each symbol. As the requests are first collected in a list before
+ ;; being processed they are still sent in order from left to right.
+ (when (and lsp-ui-sideline-show-hover (or line-changed line-modified) (lsp--capability "hoverProvider"))
+ (setq lsp-ui-sideline--last-tick-info this-tick
+ lsp-ui-sideline--previous-line this-line)
+ (save-excursion
+ (goto-char eol)
+ (while (and (> (point) bol)
+ (progn (forward-symbol -1)
+ (>= (point) bol)))
+ (let* ((symbol (thing-at-point 'symbol t))
+ (bounds (bounds-of-thing-at-point 'symbol))
+ (parsing-state (syntax-ppss))
+ (in-string (nth 3 parsing-state))
+ (outside-comment (eq (nth 4 parsing-state) nil)))
+ ;; Skip strings and comments
+ (when (and symbol (not in-string) outside-comment)
+ (push (list symbol bounds (list :line (1- line-widen) :character (- (point) bol))) symbols))))
+ (if (null symbols)
+ (lsp-ui-sideline--delete-kind 'info)
+ (let ((length-symbols (length symbols))
+ (current-index 0)
+ list-infos)
+ (--each symbols
+ (-let (((symbol bounds position) it))
+ (lsp-request-async
+ "textDocument/hover"
+ (lsp-make-hover-params :text-document doc-id :position position)
+ (lambda (info)
+ (cl-incf current-index)
+ (and info (push (list symbol bounds info) list-infos))
+ (when (or (= current-index length-symbols) (not lsp-ui-sideline-wait-for-all-symbols))
+ (lsp-ui-sideline--display-all-info list-infos tag bol eol)))
+ :error-handler
+ (lambda (&rest _)
+ (cl-incf current-index)
+ (when (or (= current-index length-symbols) (not lsp-ui-sideline-wait-for-all-symbols))
+ (lsp-ui-sideline--display-all-info list-infos tag bol eol)))
+ :mode 'tick))))))))))
+
+(defun lsp-ui-sideline--stop-p ()
+ "Return non-nil if the sideline should not be display."
+ (or (region-active-p)
+ (bound-and-true-p company-pseudo-tooltip-overlay)
+ (bound-and-true-p lsp-ui-peek--overlay)))
+
+(defun lsp-ui-sideline--hide-before-company (command)
+ "Disable the sideline before company's overlay appears.
+COMMAND is `company-pseudo-tooltip-frontend' parameter."
+ (when (memq command '(post-command update))
+ (lsp-ui-sideline--delete-ov)))
+
+(defun lsp-ui-sideline ()
+ "Show information for the current line."
+ (if (lsp-ui-sideline--stop-p)
+ (lsp-ui-sideline--delete-ov)
+ (let* ((inhibit-field-text-motion t)
+ (same-line (lsp-ui-sideline--valid-tag-p lsp-ui-sideline--tag 'line))
+ (same-width (equal (window-text-width) lsp-ui-sideline--last-width))
+ (new-tick (and same-line (not (equal (buffer-modified-tick) lsp-ui-sideline--last-tick-info))))
+ (bol (and new-tick (line-beginning-position)))
+ (eol (and new-tick (line-end-position)))
+ (this-line (and new-tick (lsp-ui-sideline--get-line bol eol)))
+ (unmodified (if new-tick (equal this-line lsp-ui-sideline--previous-line) t))
+ (buffer (current-buffer))
+ (point (point)))
+ (cond ((and unmodified same-line same-width)
+ (lsp-ui-sideline--highlight-current (point)))
+ ((not (and same-line same-width))
+ (lsp-ui-sideline--delete-ov)))
+ (when lsp-ui-sideline--timer
+ (cancel-timer lsp-ui-sideline--timer))
+ (setq lsp-ui-sideline--timer
+ (run-with-idle-timer
+ lsp-ui-sideline-delay nil
+ (lambda nil
+ ;; run lsp-ui only if current-buffer is the same.
+ (and (eq buffer (current-buffer))
+ (= point (point))
+ (lsp-ui-sideline--run buffer bol eol this-line))))))))
+
+(defun lsp-ui-sideline-toggle-symbols-info ()
+ "Toggle display of symbols information.
+This does not toggle display of flycheck diagnostics or code actions."
+ (interactive)
+ (when (bound-and-true-p lsp-ui-sideline-mode)
+ (setq lsp-ui-sideline-show-hover (not lsp-ui-sideline-show-hover))
+ (lsp-ui-sideline--run (current-buffer))))
+
+(defun lsp-ui-sideline--diagnostics-changed ()
+ "Handler for flycheck notifications."
+ (when lsp-ui-sideline-show-diagnostics
+ (let* ((buffer (current-buffer))
+ (inhibit-field-text-motion t)
+ (eol (line-end-position))
+ (bol (line-beginning-position)))
+ (lsp-ui-sideline--diagnostics buffer bol eol))))
+
+(defun lsp-ui-sideline--erase (&rest _)
+ "Remove all sideline overlays and delete last tag."
+ (when (bound-and-true-p lsp-ui-sideline-mode)
+ (ignore-errors (lsp-ui-sideline--delete-ov))))
+
+(define-minor-mode lsp-ui-sideline-mode
+ "Minor mode for showing information for current line."
+ :init-value nil
+ :group lsp-ui-sideline
+ (cond
+ (lsp-ui-sideline-mode
+ (add-hook 'post-command-hook 'lsp-ui-sideline nil t)
+ (advice-add 'company-pseudo-tooltip-frontend :before 'lsp-ui-sideline--hide-before-company)
+ (add-hook 'flycheck-after-syntax-check-hook 'lsp-ui-sideline--diagnostics-changed nil t)
+ (when lsp-ui-sideline-show-diagnostics
+ (setq-local flycheck-display-errors-function nil)))
+ (t
+ (advice-remove 'company-pseudo-tooltip-frontend 'lsp-ui-sideline--hide-before-company)
+ (lsp-ui-sideline--delete-ov)
+ (remove-hook 'flycheck-after-syntax-check-hook 'lsp-ui-sideline--diagnostics-changed t)
+ (remove-hook 'post-command-hook 'lsp-ui-sideline t)
+ (when lsp-ui-sideline-show-diagnostics
+ (kill-local-variable 'flycheck-display-errors-function)))))
+
+(defun lsp-ui-sideline-enable (enable)
+ "Enable/disable `lsp-ui-sideline-mode'."
+ (lsp-ui-sideline-mode (if enable 1 -1))
+ (if enable
+ (add-hook 'before-revert-hook 'lsp-ui-sideline--delete-ov nil t)
+ (remove-hook 'before-revert-hook 'lsp-ui-sideline--delete-ov t)))
+
+(provide 'lsp-ui-sideline)
+;;; lsp-ui-sideline.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-util.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-util.el
new file mode 100644
index 0000000..a5d92f2
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui-util.el
@@ -0,0 +1,71 @@
+;;; lsp-ui-util.el --- Utility module for Lsp-Ui -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 Shen, Jen-Chieh
+
+;; Author: Jen-Chieh Shen <jcs090218@gmail.com>
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Keywords: languages, tools
+;; Version: 6.2
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;
+;; Utility module for Lsp-Ui.
+;;
+
+;;; Code:
+
+(require 'face-remap)
+
+(defun lsp-ui-util-safe-kill-timer (timer)
+ "Safely kill the TIMER."
+ (when (timerp timer) (cancel-timer timer)))
+
+(defun lsp-ui-util-safe-delete-overlay (overlay)
+ "Safely delete the OVERLAY."
+ (when (overlayp overlay) (delete-overlay overlay)))
+
+(defun lsp-ui-util-line-number-display-width ()
+ "Safe way to get value from function `line-number-display-width'."
+ (if (bound-and-true-p display-line-numbers-mode)
+ ;; For some reason, function `line-number-display-width' gave
+ ;; us error `args-out-of-range' even we do not pass anything towards
+ ;; to it function. See the following links,
+ ;;
+ ;; - https://github.com/emacs-lsp/lsp-ui/issues/294
+ ;; - https://github.com/emacs-lsp/lsp-ui/issues/533 (duplicate)
+ (+ (or (ignore-errors (line-number-display-width)) 0) 2)
+ 0))
+
+(defun lsp-ui-util-line-string (pos)
+ "Return string at POS."
+ (when (integerp pos) (save-excursion (goto-char pos) (thing-at-point 'line))))
+
+(defun lsp-ui-util-column (&optional pos)
+ "Return column at POS."
+ (setq pos (or pos (point)))
+ (save-excursion (goto-char pos) (current-column)))
+
+(defun lsp-ui-util-text-scale-factor ()
+ "Return the factor effect by `text-scale-mode'."
+ (or (plist-get (cdr text-scale-mode-remapping) :height) 1))
+
+(provide 'lsp-ui-util)
+;;; lsp-ui-util.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui.el b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui.el
new file mode 100644
index 0000000..cbaf923
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/lsp-ui.el
@@ -0,0 +1,177 @@
+;;; lsp-ui.el --- UI modules for lsp-mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Tobias Pisani
+;; Copyright (C) 2018 Sebastien Chapuis, Fangrui Song
+
+;; Author: Sebastien Chapuis <sebastien@chapu.is>, Fangrui Song <i@maskray.me>
+;; Keywords: languages, tools
+;; URL: https://github.com/emacs-lsp/lsp-ui
+;; Package-Requires: ((emacs "26.1") (dash "2.18.0") (lsp-mode "6.0") (markdown-mode "2.3"))
+;; Version: 7.0.1
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; lsp-ui contains a series of useful UI integrations for lsp-mode, like
+;; flycheck support and code lenses.
+
+;;; Code:
+
+(require 'dash)
+(require 'lsp-protocol)
+(require 'find-func)
+
+(defconst lsp-ui-resources-dir
+ (--> (find-library-name "lsp-ui")
+ (file-name-directory it)
+ (expand-file-name "resources" it)
+ (file-name-as-directory it)
+ (and (file-directory-p it) it))
+ "Resource folder for package `lsp-ui'.")
+
+(require 'lsp-ui-sideline)
+(require 'lsp-ui-peek)
+(require 'lsp-ui-imenu)
+(require 'lsp-ui-doc)
+
+(defgroup lsp-ui nil
+ "‘lsp-ui’ contains a series of useful UI integrations for ‘lsp-mode’."
+ :group 'tools
+ :group 'convenience
+ :link '(custom-manual "(lsp-ui) Top")
+ :link '(info-link "(lsp-ui) Customizing"))
+
+(with-eval-after-load 'flycheck
+ (require 'lsp-ui-flycheck))
+
+(with-eval-after-load 'winum
+ (when (and (boundp 'winum-ignored-buffers-regexp) lsp-ui-doc-winum-ignore)
+ (add-to-list 'winum-ignored-buffers-regexp lsp-ui-doc--buffer-prefix)))
+
+(defun lsp-ui-peek--render (major string)
+ (with-temp-buffer
+ (insert string)
+ (delay-mode-hooks
+ (let ((inhibit-message t)) (funcall major))
+ (ignore-errors (font-lock-ensure)))
+ (buffer-string)))
+
+(defun lsp-ui--workspace-path (path)
+ "Return the PATH relative to the workspace.
+If the PATH is not in the workspace, it returns the original PATH."
+ (let* ((path (file-truename path))
+ (root (lsp-workspace-root path))
+ (in-workspace (and root (string-prefix-p root path))))
+ (if in-workspace
+ (substring path (length root))
+ path)))
+
+(defun lsp-ui--toggle (enable)
+ (dolist (feature '(lsp-ui-peek lsp-ui-sideline lsp-ui-doc lsp-ui-imenu))
+ (let* ((sym (--> (intern-soft (concat (symbol-name feature) "-enable"))
+ (and (boundp it) it)))
+ (value (symbol-value sym))
+ (fn (symbol-function sym)))
+ (and (or value (not enable))
+ (functionp fn)
+ (funcall fn enable)))))
+
+(defvar lsp-ui-mode-map (make-sparse-keymap))
+
+;;;###autoload
+(define-minor-mode lsp-ui-mode
+ "Toggle language server UI mode on or off.
+‘lsp-ui-mode’ is a minor mode that contains a series of useful UI
+integrations for ‘lsp-mode’. With a prefix argument ARG, enable
+language server UI mode if ARG is positive, and disable it
+otherwise. If called from Lisp, enable the mode if ARG is
+omitted or nil, and toggle it if ARG is ‘toggle’."
+ :init-value nil
+ :group lsp-ui
+ :keymap lsp-ui-mode-map
+ (lsp-ui--toggle lsp-ui-mode))
+
+;; The request is delegated to xref-backend-apropos defined in lsp-mode.
+;; xref-find-apropos does similar job but is less appealing because it splits and
+;; regex quotes the pattern. The language server likely knows more about how
+;; to do fuzzy matching.
+(defun lsp-ui-find-workspace-symbol (pattern)
+ "List project-wide symbols matching the query string PATTERN."
+ (interactive (list (read-string
+ "workspace/symbol: "
+ nil 'xref--read-pattern-history)))
+ (xref--find-xrefs pattern 'apropos pattern nil))
+
+(defun lsp-ui--location< (x y)
+ "Compares two triples X and Y.
+Both should have the form (FILENAME LINE COLUMN)."
+ (if (not (string= (car x) (car y)))
+ (string< (car x) (car y))
+ (if (not (= (cadr x) (cadr y)))
+ (< (cadr x) (cadr y))
+ (< (caddr x) (caddr y)))))
+
+(defun lsp-ui--reference-triples (extra)
+ "Return references as a list of (FILENAME LINE COLUMN) triples given EXTRA."
+ (let ((refs (lsp-request "textDocument/references"
+ (append (lsp--text-document-position-params) extra))))
+ (sort
+ (mapcar
+ (-lambda ((&Location :uri :range (&Range :start (&Position :line :character))))
+ (list (lsp--uri-to-path uri) line character))
+ refs)
+ #'lsp-ui--location<)))
+
+;; TODO Make it efficient
+(defun lsp-ui-find-next-reference (&optional extra)
+ "Find next reference of the symbol at point."
+ (interactive)
+ (let* ((cur (list buffer-file-name (1- (line-number-at-pos)) (- (point) (line-beginning-position))))
+ (refs (lsp-ui--reference-triples extra))
+ (idx -1)
+ (res (-first (lambda (ref) (cl-incf idx) (lsp-ui--location< cur ref)) refs)))
+ (if res
+ (progn
+ (find-file (car res))
+ (goto-char 1)
+ (forward-line (cadr res))
+ (forward-char (caddr res))
+ (cons idx (length refs)))
+ (cons 0 0))))
+
+;; TODO Make it efficient
+(defun lsp-ui-find-prev-reference (&optional extra)
+ "Find previous reference of the symbol at point."
+ (interactive)
+ (let* ((cur (list buffer-file-name (1- (line-number-at-pos)) (- (point) (line-beginning-position))))
+ (refs (lsp-ui--reference-triples extra))
+ (idx -1)
+ (res (-last (lambda (ref) (and (lsp-ui--location< ref cur) (cl-incf idx))) refs)))
+ (if res
+ (progn
+ (find-file (car res))
+ (goto-char 1)
+ (forward-line (cadr res))
+ (forward-char (caddr res))
+ (cons idx (length refs)))
+ (cons 0 0))))
+
+
+(provide 'lsp-ui)
+;;; lsp-ui.el ends here
diff --git a/emacs.d/elpa/lsp-ui-20210718.445/resources/lightbulb.png b/emacs.d/elpa/lsp-ui-20210718.445/resources/lightbulb.png
new file mode 100644
index 0000000..7c1ad08
--- /dev/null
+++ b/emacs.d/elpa/lsp-ui-20210718.445/resources/lightbulb.png
Binary files differ
diff --git a/emacs.d/elpa/lv-20200507.1518/lv-autoloads.el b/emacs.d/elpa/lv-20200507.1518/lv-autoloads.el
new file mode 100644
index 0000000..61b1079
--- /dev/null
+++ b/emacs.d/elpa/lv-20200507.1518/lv-autoloads.el
@@ -0,0 +1,22 @@
+;;; lv-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "lv" "lv.el" (0 0 0 0))
+;;; Generated autoloads from lv.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lv" '("lv-")))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; lv-autoloads.el ends here
diff --git a/emacs.d/elpa/lv-20200507.1518/lv-pkg.el b/emacs.d/elpa/lv-20200507.1518/lv-pkg.el
new file mode 100644
index 0000000..0ef0d4b
--- /dev/null
+++ b/emacs.d/elpa/lv-20200507.1518/lv-pkg.el
@@ -0,0 +1,2 @@
+;;; Generated package description from lv-20200507.1518/lv.el -*- no-byte-compile: t -*-
+(define-package "lv" "20200507.1518" "Other echo area" 'nil :commit "2d553787aca1aceb3e6927e426200e9bb9f056f1" :authors '(("Oleh Krehel")) :maintainer '("Oleh Krehel"))
diff --git a/emacs.d/elpa/lv-20200507.1518/lv.el b/emacs.d/elpa/lv-20200507.1518/lv.el
new file mode 100644
index 0000000..cafcbb1
--- /dev/null
+++ b/emacs.d/elpa/lv-20200507.1518/lv.el
@@ -0,0 +1,150 @@
+;;; lv.el --- Other echo area
+;; Package-Version: 20200507.1518
+;; Package-Commit: 2d553787aca1aceb3e6927e426200e9bb9f056f1
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This package provides `lv-message' intended to be used in place of
+;; `message' when semi-permanent hints are needed, in order to not
+;; interfere with Echo Area.
+;;
+;; "Я тихо-тихо пiдглÑдаю,
+;; І Ñ‚iшуÑÑ Ñобi, Ñк бачу то,
+;; Шо Ñтрашить i не пiдпуÑкає,
+;; Ð iншi п’ють тебе, Ñк воду пiÑок."
+;; -- Ðндрій Кузьменко, L.V.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defgroup lv nil
+ "The other echo area."
+ :group 'minibuffer
+ :group 'hydra)
+
+(defcustom lv-use-separator nil
+ "Whether to draw a line between the LV window and the Echo Area."
+ :group 'lv
+ :type 'boolean)
+
+(defcustom lv-use-padding nil
+ "Whether to use horizontal padding in the LV window."
+ :group 'lv
+ :type 'boolean)
+
+(defface lv-separator
+ '((((class color) (background light)) :background "grey80")
+ (((class color) (background dark)) :background "grey30"))
+ "Face used to draw line between the lv window and the echo area.
+This is only used if option `lv-use-separator' is non-nil.
+Only the background color is significant."
+ :group 'lv)
+
+(defvar lv-wnd nil
+ "Holds the current LV window.")
+
+(defvar display-line-numbers)
+(defvar display-fill-column-indicator)
+(defvar tab-line-format)
+
+(defvar lv-window-hook nil
+ "Hook to run by `lv-window' when a new window is created.")
+
+(defun lv-window ()
+ "Ensure that LV window is live and return it."
+ (if (window-live-p lv-wnd)
+ lv-wnd
+ (let ((ori (selected-window))
+ buf)
+ (prog1 (setq lv-wnd
+ (select-window
+ (let ((ignore-window-parameters t))
+ (split-window
+ (frame-root-window) -1 'below))
+ 'norecord))
+ (if (setq buf (get-buffer " *LV*"))
+ (switch-to-buffer buf 'norecord)
+ (switch-to-buffer " *LV*" 'norecord)
+ (fundamental-mode)
+ (set-window-hscroll lv-wnd 0)
+ (setq window-size-fixed t)
+ (setq mode-line-format nil)
+ (setq header-line-format nil)
+ (setq tab-line-format nil)
+ (setq cursor-type nil)
+ (setq display-line-numbers nil)
+ (setq display-fill-column-indicator nil)
+ (set-window-dedicated-p lv-wnd t)
+ (set-window-parameter lv-wnd 'no-other-window t)
+ (run-hooks 'lv-window-hook))
+ (select-window ori 'norecord)))))
+
+(defvar golden-ratio-mode)
+
+(defvar lv-force-update nil
+ "When non-nil, `lv-message' will refresh even for the same string.")
+
+(defun lv--pad-to-center (str width)
+ "Pad STR with spaces on the left to be centered to WIDTH."
+ (let* ((strs (split-string str "\n"))
+ (padding (make-string
+ (/ (- width (length (car strs))) 2)
+ ?\ )))
+ (mapconcat (lambda (s) (concat padding s)) strs "\n")))
+
+(defun lv-message (format-string &rest args)
+ "Set LV window contents to (`format' FORMAT-STRING ARGS)."
+ (let* ((str (apply #'format format-string args))
+ (n-lines (cl-count ?\n str))
+ deactivate-mark
+ golden-ratio-mode)
+ (with-selected-window (lv-window)
+ (when lv-use-padding
+ (setq str (lv--pad-to-center str (window-width))))
+ (unless (and (string= (buffer-string) str)
+ (null lv-force-update))
+ (delete-region (point-min) (point-max))
+ (insert str)
+ (when (and (window-system) lv-use-separator)
+ (unless (looking-back "\n" nil)
+ (insert "\n"))
+ (insert
+ (propertize "__" 'face 'lv-separator 'display '(space :height (1)))
+ (propertize "\n" 'face 'lv-separator 'line-height t)))
+ (set (make-local-variable 'window-min-height) n-lines)
+ (setq truncate-lines (> n-lines 1))
+ (let ((window-resize-pixelwise t)
+ (window-size-fixed nil))
+ (fit-window-to-buffer nil nil 1)))
+ (goto-char (point-min)))))
+
+(defun lv-delete-window ()
+ "Delete LV window and kill its buffer."
+ (when (window-live-p lv-wnd)
+ (let ((buf (window-buffer lv-wnd)))
+ (delete-window lv-wnd)
+ (kill-buffer buf))))
+
+(provide 'lv)
+
+;;; lv.el ends here
diff --git a/emacs.d/elpa/project-0.6.0.signed b/emacs.d/elpa/project-0.6.0.signed
new file mode 100644
index 0000000..f4efdd2
--- /dev/null
+++ b/emacs.d/elpa/project-0.6.0.signed
@@ -0,0 +1 @@
+Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2021-04-29T12:05:02+0300 using RSA \ No newline at end of file
diff --git a/emacs.d/elpa/project-0.6.0/project-autoloads.el b/emacs.d/elpa/project-0.6.0/project-autoloads.el
new file mode 100644
index 0000000..4010bb1
--- /dev/null
+++ b/emacs.d/elpa/project-0.6.0/project-autoloads.el
@@ -0,0 +1,234 @@
+;;; project-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "project" "project.el" (0 0 0 0))
+;;; Generated autoloads from project.el
+
+(autoload 'project-current "project" "\
+Return the project instance in DIRECTORY, defaulting to `default-directory'.
+
+When no project is found in that directory, the result depends on
+the value of MAYBE-PROMPT: if it is nil or omitted, return nil,
+else ask the user for a directory in which to look for the
+project, and if no project is found there, return a \"transient\"
+project instance.
+
+The \"transient\" project instance is a special kind of value
+which denotes a project rooted in that directory and includes all
+the files under the directory except for those that should be
+ignored (per `project-ignores').
+
+See the doc string of `project-find-functions' for the general form
+of the project instance object.
+
+\(fn &optional MAYBE-PROMPT DIRECTORY)" nil nil)
+
+(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map "!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) (define-key map "f" 'project-find-file) (define-key map "F" 'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) (define-key map "s" 'project-shell) (define-key map "d" 'project-dired) (define-key map "v" 'project-vc-dir) (define-key map "c" 'project-compile) (define-key map "e" 'project-eshell) (define-key map "k" 'project-kill-buffers) (define-key map "p" 'project-switch-project) (define-key map "g" 'project-find-regexp) (define-key map "G" 'project-or-external-find-regexp) (define-key map "r" 'project-query-replace-regexp) (define-key map "x" 'project-execute-extended-command) map) "\
+Keymap for project commands.")
+ (define-key ctl-x-map "p" project-prefix-map)
+
+(autoload 'project-other-window-command "project" "\
+Run project command, displaying resultant buffer in another window.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-window-map}" t nil)
+ (define-key ctl-x-4-map "p" #'project-other-window-command)
+
+(autoload 'project-other-frame-command "project" "\
+Run project command, displaying resultant buffer in another frame.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-frame-map}" t nil)
+ (define-key ctl-x-5-map "p" #'project-other-frame-command)
+
+(autoload 'project-other-tab-command "project" "\
+Run project command, displaying resultant buffer in a new tab.
+
+The following commands are available:
+
+\\{project-prefix-map}" t nil)
+
+(when (bound-and-true-p tab-prefix-map) (define-key tab-prefix-map "p" #'project-other-tab-command))
+
+(autoload 'project-find-regexp "project" "\
+Find all matches for REGEXP in the current project's roots.
+With \\[universal-argument] prefix, you can specify the directory
+to search in, and the file name pattern to search for. The
+pattern may use abbreviations defined in `grep-files-aliases',
+e.g. entering `ch' is equivalent to `*.[ch]'. As whitespace
+triggers completion when entering a pattern, including it
+requires quoting, e.g. `\\[quoted-insert]<space>'.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'project-or-external-find-regexp "project" "\
+Find all matches for REGEXP in the project roots or external roots.
+With \\[universal-argument] prefix, you can specify the file name
+pattern to search for.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'project-find-file "project" "\
+Visit a file (with completion) in the current project.
+
+The completion default is the filename at point, determined by
+`thing-at-point' (whether such file exists or not)." t nil)
+
+(autoload 'project-or-external-find-file "project" "\
+Visit a file (with completion) in the current project or external roots.
+
+The completion default is the filename at point, determined by
+`thing-at-point' (whether such file exists or not)." t nil)
+
+(autoload 'project-dired "project" "\
+Start Dired in the current project's root." t nil)
+
+(autoload 'project-vc-dir "project" "\
+Run VC-Dir in the current project's root." t nil)
+
+(autoload 'project-shell "project" "\
+Start an inferior shell in the current project's root directory.
+If a buffer already exists for running a shell in the project's root,
+switch to it. Otherwise, create a new shell buffer.
+With \\[universal-argument] prefix arg, create a new inferior shell buffer even
+if one already exists." t nil)
+
+(autoload 'project-eshell "project" "\
+Start Eshell in the current project's root directory.
+If a buffer already exists for running Eshell in the project's root,
+switch to it. Otherwise, create a new Eshell buffer.
+With \\[universal-argument] prefix arg, create a new Eshell buffer even
+if one already exists." t nil)
+
+(autoload 'project-async-shell-command "project" "\
+Run `async-shell-command' in the current project's root directory." t nil)
+
+(function-put 'project-async-shell-command 'interactive-only 'async-shell-command)
+
+(autoload 'project-shell-command "project" "\
+Run `shell-command' in the current project's root directory." t nil)
+
+(function-put 'project-shell-command 'interactive-only 'shell-command)
+
+(autoload 'project-search "project" "\
+Search for REGEXP in all the files of the project.
+Stops when a match is found.
+To continue searching for the next match, use the
+command \\[fileloop-continue].
+
+\(fn REGEXP)" t nil)
+
+(autoload 'project-query-replace-regexp "project" "\
+Query-replace REGEXP in all the files of the project.
+Stops when a match is found and prompts for whether to replace it.
+If you exit the query-replace, you can later continue the query-replace
+loop using the command \\[fileloop-continue].
+
+\(fn FROM TO)" t nil)
+
+(autoload 'project-compile "project" "\
+Run `compile' in the project root." t nil)
+
+(function-put 'project-compile 'interactive-only 'compile)
+
+(autoload 'project-switch-to-buffer "project" "\
+Display buffer BUFFER-OR-NAME in the selected window.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+\(fn BUFFER-OR-NAME)" t nil)
+
+(autoload 'project-display-buffer "project" "\
+Display BUFFER-OR-NAME in some window, without selecting it.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+This function uses `display-buffer' as a subroutine, which see
+for how it is determined where the buffer will be displayed.
+
+\(fn BUFFER-OR-NAME)" t nil)
+
+(autoload 'project-display-buffer-other-frame "project" "\
+Display BUFFER-OR-NAME preferably in another frame.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+This function uses `display-buffer-other-frame' as a subroutine,
+which see for how it is determined where the buffer will be
+displayed.
+
+\(fn BUFFER-OR-NAME)" t nil)
+
+(autoload 'project-kill-buffers "project" "\
+Kill the buffers belonging to the current project.
+Two buffers belong to the same project if their project
+instances, as reported by `project-current' in each buffer, are
+identical. Only the buffers that match a condition in
+`project-kill-buffer-conditions' will be killed. If NO-CONFIRM
+is non-nil, the command will not ask the user for confirmation.
+NO-CONFIRM is always nil when the command is invoked
+interactively.
+
+\(fn &optional NO-CONFIRM)" t nil)
+
+(autoload 'project-remember-project "project" "\
+Add project PR to the front of the project list.
+Save the result in `project-list-file' if the list of projects has changed.
+
+\(fn PR)" nil nil)
+
+(autoload 'project-remove-known-project "project" "\
+Remove directory PROJECT-ROOT from the project list.
+PROJECT-ROOT is the root directory of a known project listed in
+the project list.
+
+\(fn PROJECT-ROOT)" t nil)
+
+(autoload 'project-known-project-roots "project" "\
+Return the list of root directories of all known projects." nil nil)
+
+(autoload 'project-execute-extended-command "project" "\
+Execute an extended command in project root." t nil)
+
+(function-put 'project-execute-extended-command 'interactive-only 'command-execute)
+
+(autoload 'project-switch-project "project" "\
+\"Switch\" to another project by running an Emacs command.
+The available commands are presented as a dispatch menu
+made from `project-switch-commands'.
+
+When called in a program, it will use the project corresponding
+to directory DIR.
+
+\(fn DIR)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "project" '("project-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("project-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; project-autoloads.el ends here
diff --git a/emacs.d/elpa/project-0.6.0/project-pkg.el b/emacs.d/elpa/project-0.6.0/project-pkg.el
new file mode 100644
index 0000000..47bac26
--- /dev/null
+++ b/emacs.d/elpa/project-0.6.0/project-pkg.el
@@ -0,0 +1,2 @@
+;; Generated package description from project.el -*- no-byte-compile: t -*-
+(define-package "project" "0.6.0" "Operations on the current project" '((emacs "26.1") (xref "1.0.2")) :url "https://elpa.gnu.org/packages/project.html")
diff --git a/emacs.d/elpa/project-0.6.0/project.el b/emacs.d/elpa/project-0.6.0/project.el
new file mode 100644
index 0000000..d47d9d7
--- /dev/null
+++ b/emacs.d/elpa/project-0.6.0/project.el
@@ -0,0 +1,1401 @@
+;;; project.el --- Operations on the current project -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021 Free Software Foundation, Inc.
+;; Version: 0.6.0
+;; Package-Requires: ((emacs "26.1") (xref "1.0.2"))
+
+;; This is a GNU ELPA :core package. Avoid using functionality that
+;; not compatible with the version of Emacs recorded above.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; NOTE: The project API is still experimental and can change in major,
+;; backward-incompatible ways. Everyone is encouraged to try it, and
+;; report to us any problems or use cases we hadn't anticipated, by
+;; sending an email to emacs-devel, or `M-x report-emacs-bug'.
+;;
+;; This file contains generic infrastructure for dealing with
+;; projects, some utility functions, and commands using that
+;; infrastructure.
+;;
+;; The goal is to make it easier for Lisp programs to operate on the
+;; current project, without having to know which package handles
+;; detection of that project type, parsing its config files, etc.
+;;
+;; This file consists of following parts:
+;;
+;; Infrastructure (the public API):
+;;
+;; Function `project-current' that returns the current project
+;; instance based on the value of the hook `project-find-functions',
+;; and several generic functions that act on it.
+;;
+;; `project-root' must be defined for every project.
+;; `project-files' can be overridden for performance purposes.
+;; `project-ignores' and `project-external-roots' describe the project
+;; files and its relations to external directories. `project-files'
+;; should be consistent with `project-ignores'.
+;;
+;; This list can change in future versions.
+;;
+;; VC project:
+;;
+;; Originally conceived as an example implementation, now it's a
+;; relatively fast backend that delegates to 'git ls-files' or 'hg
+;; status' to list the project's files. It honors the VC ignore
+;; files, but supports additions to the list using the user option
+;; `project-vc-ignores' (usually through .dir-locals.el).
+;;
+;; Utils:
+;;
+;; `project-combine-directories' and `project-subtract-directories',
+;; mainly for use in the abovementioned generics' implementations.
+;;
+;; `project-known-project-roots' and `project-remember-project' to
+;; interact with the "known projects" list.
+;;
+;; Commands:
+;;
+;; `project-prefix-map' contains the full list of commands defined in
+;; this package. This map uses the prefix `C-x p' by default.
+;; Type `C-x p f' to find file in the current project.
+;; Type `C-x p C-h' to see all available commands and bindings.
+;;
+;; All commands defined in this package are implemented using the
+;; public API only. As a result, they will work with any project
+;; backend that follows the protocol.
+;;
+;; Any third-party code that wants to use this package should likewise
+;; target the public API. Use any of the built-in commands as the
+;; example.
+;;
+;; How to create a new backend:
+;;
+;; - Consider whether you really should, or whether there are other
+;; ways to reach your goals. If the backend's performance is
+;; significantly lower than that of the built-in one, and it's first
+;; in the list, it will affect all commands that use it. Unless you
+;; are going to be using it only yourself or in special circumstances,
+;; you will probably want it to be fast, and it's unlikely to be a
+;; trivial endeavor. `project-files' is the method to optimize (the
+;; default implementation gets slower the more files the directory
+;; has, and the longer the list of ignores is).
+;;
+;; - Choose the format of the value that represents a project for your
+;; backend (we call it project instance). Don't use any of the
+;; formats from other backends. The format can be arbitrary, as long
+;; as the datatype is something `cl-defmethod' can dispatch on. The
+;; value should be stable (when compared with `equal') across
+;; invocations, meaning calls to that function from buffers belonging
+;; to the same project should return equal values.
+;;
+;; - Write a new function that will determine the current project
+;; based on the directory and add it to `project-find-functions'
+;; (which see) using `add-hook'. It is a good idea to depend on the
+;; directory only, and not on the current major mode, for example.
+;; Because the usual expectation is that all files in the directory
+;; belong to the same project (even if some/most of them are ignored).
+;;
+;; - Define new methods for some or all generic functions for this
+;; backend using `cl-defmethod'. A `project-root' method is
+;; mandatory, `project-files' is recommended, the rest are optional.
+
+;;; TODO:
+
+;; * Reliably cache the list of files in the project, probably using
+;; filenotify.el (if supported) to invalidate. And avoiding caching
+;; if it's not available (manual cache invalidation is not nice).
+;;
+;; * Build tool related functionality. Start with a `project-build'
+;; command, which should provide completions on tasks to run, and
+;; maybe allow entering some additional arguments. This might
+;; be handled better with a separate API, though. Then we won't
+;; force every project backend to be aware of the build tool(s) the
+;; project is using.
+;;
+;; * Command to (re)build the tag files in all project roots. To that
+;; end, we might need to add a way to provide file whitelist
+;; wildcards for each root to limit etags to certain files (in
+;; addition to the blacklist provided by ignores), and/or allow
+;; specifying additional tag regexps.
+;;
+;; * UI for the user to be able to pick the current project for the
+;; whole Emacs session, independent of the current directory. Or,
+;; in the more advanced case, open a set of projects, and have some
+;; project-related commands to use them all. E.g., have a command
+;; to search for a regexp across all open projects.
+;;
+;; * Support for project-local variables: a UI to edit them, and a
+;; utility function to retrieve a value. Probably useless without
+;; support in various built-in commands. In the API, we might get
+;; away with only adding a `project-configuration-directory' method,
+;; defaulting to the project root the current file/buffer is in.
+;; And prompting otherwise. How to best mix that with backends that
+;; want to set/provide certain variables themselves, is up for
+;; discussion.
+
+;;; Code:
+
+(require 'cl-generic)
+(require 'seq)
+(eval-when-compile (require 'subr-x))
+
+(defgroup project nil
+ "Operations on the current project."
+ :version "28.1"
+ :group 'tools)
+
+(defvar project-find-functions (list #'project-try-vc)
+ "Special hook to find the project containing a given directory.
+Each functions on this hook is called in turn with one
+argument, the directory in which to look, and should return
+either nil to mean that it is not applicable, or a project instance.
+The exact form of the project instance is up to each respective
+function; the only practical limitation is to use values that
+`cl-defmethod' can dispatch on, like a cons cell, or a list, or a
+CL struct.")
+
+(defvar project-current-inhibit-prompt nil
+ "Non-nil to skip prompting the user in `project-current'.")
+
+;;;###autoload
+(defun project-current (&optional maybe-prompt directory)
+ "Return the project instance in DIRECTORY, defaulting to `default-directory'.
+
+When no project is found in that directory, the result depends on
+the value of MAYBE-PROMPT: if it is nil or omitted, return nil,
+else ask the user for a directory in which to look for the
+project, and if no project is found there, return a \"transient\"
+project instance.
+
+The \"transient\" project instance is a special kind of value
+which denotes a project rooted in that directory and includes all
+the files under the directory except for those that should be
+ignored (per `project-ignores').
+
+See the doc string of `project-find-functions' for the general form
+of the project instance object."
+ (unless directory (setq directory default-directory))
+ (let ((pr (project--find-in-directory directory)))
+ (cond
+ (pr)
+ ((unless project-current-inhibit-prompt
+ maybe-prompt)
+ (setq directory (project-prompt-project-dir)
+ pr (project--find-in-directory directory))))
+ (when maybe-prompt
+ (if pr
+ (project-remember-project pr)
+ (project--remove-from-project-list
+ directory "Project `%s' not found; removed from list")
+ (setq pr (cons 'transient directory))))
+ pr))
+
+(defun project--find-in-directory (dir)
+ (run-hook-with-args-until-success 'project-find-functions dir))
+
+(defvar project--within-roots-fallback nil)
+
+(cl-defgeneric project-root (project)
+ "Return root directory of the current project.
+
+It usually contains the main build file, dependencies
+configuration file, etc. Though neither is mandatory.
+
+The directory name must be absolute.")
+
+(cl-defmethod project-root (project
+ &context (project--within-roots-fallback
+ (eql nil)))
+ (car (project-roots project)))
+
+(cl-defgeneric project-roots (project)
+ "Return the list containing the current project root.
+
+The function is obsolete, all projects have one main root anyway,
+and the rest should be possible to express through
+`project-external-roots'."
+ ;; FIXME: Can we specify project's version here?
+ ;; FIXME: Could we make this affect cl-defmethod calls too?
+ (declare (obsolete project-root "0.3.0"))
+ (let ((project--within-roots-fallback t))
+ (list (project-root project))))
+
+;; FIXME: Add MODE argument, like in `ede-source-paths'?
+(cl-defgeneric project-external-roots (_project)
+ "Return the list of external roots for PROJECT.
+
+It's the list of directories outside of the project that are
+still related to it. If the project deals with source code then,
+depending on the languages used, this list should include the
+headers search path, load path, class path, and so on."
+ nil)
+
+(cl-defgeneric project-ignores (_project _dir)
+ "Return the list of glob patterns to ignore inside DIR.
+Patterns can match both regular files and directories.
+To root an entry, start it with `./'. To match directories only,
+end it with `/'. DIR must be either `project-root' or one of
+`project-external-roots'."
+ ;; TODO: Document and support regexp ignores as used by Hg.
+ ;; TODO: Support whitelist entries.
+ (require 'grep)
+ (defvar grep-find-ignored-files)
+ (nconc
+ (mapcar
+ (lambda (dir)
+ (concat dir "/"))
+ vc-directory-exclusion-list)
+ grep-find-ignored-files))
+
+(defun project--file-completion-table (all-files)
+ (lambda (string pred action)
+ (cond
+ ((eq action 'metadata)
+ '(metadata . ((category . project-file))))
+ (t
+ (complete-with-action action all-files string pred)))))
+
+(cl-defmethod project-root ((project (head transient)))
+ (cdr project))
+
+(cl-defgeneric project-files (project &optional dirs)
+ "Return a list of files in directories DIRS in PROJECT.
+DIRS is a list of absolute directories; it should be some
+subset of the project root and external roots.
+
+The default implementation uses `find-program'. PROJECT is used
+to find the list of ignores for each directory."
+ (mapcan
+ (lambda (dir)
+ (project--files-in-directory dir
+ (project--dir-ignores project dir)))
+ (or dirs
+ (list (project-root project)))))
+
+(defun project--files-in-directory (dir ignores &optional files)
+ (require 'find-dired)
+ (require 'xref)
+ (defvar find-name-arg)
+ (let* ((default-directory dir)
+ ;; Make sure ~/ etc. in local directory name is
+ ;; expanded and not left for the shell command
+ ;; to interpret.
+ (localdir (file-name-unquote (file-local-name (expand-file-name dir))))
+ (command (format "%s %s %s -type f %s -print0"
+ find-program
+ ;; In case DIR is a symlink.
+ (file-name-as-directory localdir)
+ (xref--find-ignores-arguments ignores localdir)
+ (if files
+ (concat (shell-quote-argument "(")
+ " " find-name-arg " "
+ (mapconcat
+ #'shell-quote-argument
+ (split-string files)
+ (concat " -o " find-name-arg " "))
+ " "
+ (shell-quote-argument ")"))
+ "")))
+ (output (with-output-to-string
+ (with-current-buffer standard-output
+ (let ((status
+ (process-file-shell-command command nil t)))
+ (unless (zerop status)
+ (error "File listing failed: %s" (buffer-string))))))))
+ (project--remote-file-names
+ (sort (split-string output "\0" t)
+ #'string<))))
+
+(defun project--remote-file-names (local-files)
+ "Return LOCAL-FILES as if they were on the system of `default-directory'.
+Also quote LOCAL-FILES if `default-directory' is quoted."
+ (let ((remote-id (file-remote-p default-directory)))
+ (if (not remote-id)
+ (if (file-name-quoted-p default-directory)
+ (mapcar #'file-name-quote local-files)
+ local-files)
+ (mapcar (lambda (file)
+ (concat remote-id file))
+ local-files))))
+
+(defgroup project-vc nil
+ "Project implementation based on the VC package."
+ :version "25.1"
+ :group 'project)
+
+(defcustom project-vc-ignores nil
+ "List of patterns to add to `project-ignores'."
+ :type '(repeat string)
+ :safe #'listp)
+
+(defcustom project-vc-merge-submodules t
+ "Non-nil to consider submodules part of the parent project.
+
+After changing this variable (using Customize or .dir-locals.el)
+you might have to restart Emacs to see the effect."
+ :type 'boolean
+ :version "28.1"
+ :package-version '(project . "0.2.0")
+ :safe #'booleanp)
+
+;; FIXME: Using the current approach, major modes are supposed to set
+;; this variable to a buffer-local value. So we don't have access to
+;; the "external roots" of language A from buffers of language B, which
+;; seems desirable in multi-language projects, at least for some
+;; potential uses, like "jump to a file in project or external dirs".
+;;
+;; We could add a second argument to this function: a file extension,
+;; or a language name. Some projects will know the set of languages
+;; used in them; for others, like VC-based projects, we'll need
+;; auto-detection. I see two options:
+;;
+;; - That could be implemented as a separate second hook, with a
+;; list of functions that return file extensions.
+;;
+;; - This variable will be turned into a hook with "append" semantics,
+;; and each function in it will perform auto-detection when passed
+;; nil instead of an actual file extension. Then this hook will, in
+;; general, be modified globally, and not from major mode functions.
+;;
+;; The second option seems simpler, but the first one has the
+;; advantage that the user could override the list of languages used
+;; in a project via a directory-local variable, thus skipping
+;; languages they're not working on personally (in a big project), or
+;; working around problems in language detection (the detection logic
+;; might be imperfect for the project in question, or it might work
+;; too slowly for the user's taste).
+(defvar project-vc-external-roots-function (lambda () tags-table-list)
+ "Function that returns a list of external roots.
+
+It should return a list of directory roots that contain source
+files related to the current buffer.
+
+The directory names should be absolute. Used in the VC project
+backend implementation of `project-external-roots'.")
+
+(defun project-try-vc (dir)
+ (let* ((backend
+ ;; FIXME: This is slow. Cache it.
+ (ignore-errors (vc-responsible-backend dir)))
+ (root
+ (pcase backend
+ ('Git
+ ;; Don't stop at submodule boundary.
+ ;; FIXME: Cache for a shorter time.
+ (or (vc-file-getprop dir 'project-git-root)
+ (let ((root (vc-call-backend backend 'root dir)))
+ (vc-file-setprop
+ dir 'project-git-root
+ (if (and
+ ;; FIXME: Invalidate the cache when the value
+ ;; of this variable changes.
+ (project--vc-merge-submodules-p root)
+ (project--submodule-p root))
+ (let* ((parent (file-name-directory
+ (directory-file-name root))))
+ (vc-call-backend backend 'root parent))
+ root)))))
+ ('nil nil)
+ (_ (ignore-errors (vc-call-backend backend 'root dir))))))
+ (and root (cons 'vc root))))
+
+(defun project--submodule-p (root)
+ ;; XXX: We only support Git submodules for now.
+ ;;
+ ;; For submodules, at least, we expect the users to prefer them to
+ ;; be considered part of the parent project. For those who don't,
+ ;; there is the custom var now.
+ ;;
+ ;; Some users may also set up things equivalent to Git submodules
+ ;; using "git worktree" (for example). However, we expect that most
+ ;; of them would prefer to treat those as separate projects anyway.
+ (let* ((gitfile (expand-file-name ".git" root)))
+ (cond
+ ((file-directory-p gitfile)
+ nil)
+ ((with-temp-buffer
+ (insert-file-contents gitfile)
+ (goto-char (point-min))
+ ;; Kind of a hack to distinguish a submodule from
+ ;; other cases of .git files pointing elsewhere.
+ (looking-at "gitdir: [./]+/\\.git/modules/"))
+ t)
+ (t nil))))
+
+(cl-defmethod project-root ((project (head vc)))
+ (cdr project))
+
+(cl-defmethod project-external-roots ((project (head vc)))
+ (project-subtract-directories
+ (project-combine-directories
+ (mapcar
+ #'file-name-as-directory
+ (funcall project-vc-external-roots-function)))
+ (list (project-root project))))
+
+(cl-defmethod project-files ((project (head vc)) &optional dirs)
+ (mapcan
+ (lambda (dir)
+ (let ((ignores (project--value-in-dir 'project-vc-ignores dir))
+ backend)
+ (if (and (file-equal-p dir (cdr project))
+ (setq backend (vc-responsible-backend dir))
+ (cond
+ ((eq backend 'Hg))
+ ((and (eq backend 'Git)
+ (or
+ (not ignores)
+ (version<= "1.9" (vc-git--program-version)))))))
+ (project--vc-list-files dir backend ignores)
+ (project--files-in-directory
+ dir
+ (project--dir-ignores project dir)))))
+ (or dirs
+ (list (project-root project)))))
+
+(declare-function vc-git--program-version "vc-git")
+(declare-function vc-git--run-command-string "vc-git")
+(declare-function vc-hg-command "vc-hg")
+
+(defun project--vc-list-files (dir backend extra-ignores)
+ (pcase backend
+ (`Git
+ (let ((default-directory (expand-file-name (file-name-as-directory dir)))
+ (args '("-z"))
+ files)
+ ;; Include unregistered.
+ (setq args (append args '("-c" "-o" "--exclude-standard")))
+ (when extra-ignores
+ (setq args (append args
+ (cons "--"
+ (mapcar
+ (lambda (i)
+ (format
+ ":(exclude,glob,top)%s"
+ (if (string-match "\\*\\*" i)
+ ;; Looks like pathspec glob
+ ;; format already.
+ i
+ (if (string-match "\\./" i)
+ ;; ./abc -> abc
+ (setq i (substring i 2))
+ ;; abc -> **/abc
+ (setq i (concat "**/" i))
+ ;; FIXME: '**/abc' should also
+ ;; match a directory with that
+ ;; name, but doesn't (git 2.25.1).
+ ;; Maybe we should replace
+ ;; such entries with two.
+ (if (string-match "/\\'" i)
+ ;; abc/ -> abc/**
+ (setq i (concat i "**"))))
+ i)))
+ extra-ignores)))))
+ (setq files
+ (mapcar
+ (lambda (file) (concat default-directory file))
+ (split-string
+ (apply #'vc-git--run-command-string nil "ls-files" args)
+ "\0" t)))
+ (when (project--vc-merge-submodules-p default-directory)
+ ;; Unfortunately, 'ls-files --recurse-submodules' conflicts with '-o'.
+ (let* ((submodules (project--git-submodules))
+ (sub-files
+ (mapcar
+ (lambda (module)
+ (when (file-directory-p module)
+ (project--vc-list-files
+ (concat default-directory module)
+ backend
+ extra-ignores)))
+ submodules)))
+ (setq files
+ (apply #'nconc files sub-files))))
+ ;; 'git ls-files' returns duplicate entries for merge conflicts.
+ ;; XXX: Better solutions welcome, but this seems cheap enough.
+ (delete-consecutive-dups files)))
+ (`Hg
+ (let ((default-directory (expand-file-name (file-name-as-directory dir)))
+ args)
+ ;; Include unregistered.
+ (setq args (nconc args '("-mcardu" "--no-status" "-0")))
+ (when extra-ignores
+ (setq args (nconc args
+ (mapcan
+ (lambda (i)
+ (list "--exclude" i))
+ extra-ignores))))
+ (with-temp-buffer
+ (apply #'vc-hg-command t 0 "." "status" args)
+ (mapcar
+ (lambda (s) (concat default-directory s))
+ (split-string (buffer-string) "\0" t)))))))
+
+(defun project--vc-merge-submodules-p (dir)
+ (project--value-in-dir
+ 'project-vc-merge-submodules
+ dir))
+
+(defun project--git-submodules ()
+ ;; 'git submodule foreach' is much slower.
+ (condition-case nil
+ (with-temp-buffer
+ (insert-file-contents ".gitmodules")
+ (let (res)
+ (goto-char (point-min))
+ (while (re-search-forward "path *= *\\(.+\\)" nil t)
+ (push (match-string 1) res))
+ (nreverse res)))
+ (file-missing nil)))
+
+(cl-defmethod project-ignores ((project (head vc)) dir)
+ (let* ((root (cdr project))
+ backend)
+ (append
+ (when (file-equal-p dir root)
+ (setq backend (vc-responsible-backend root))
+ (delq
+ nil
+ (mapcar
+ (lambda (entry)
+ (cond
+ ((eq ?! (aref entry 0))
+ ;; No support for whitelisting (yet).
+ nil)
+ ((string-match "\\(/\\)[^/]" entry)
+ ;; FIXME: This seems to be Git-specific.
+ ;; And / in the entry (start or even the middle) means
+ ;; the pattern is "rooted". Or actually it is then
+ ;; relative to its respective .gitignore (of which there
+ ;; could be several), but we only support .gitignore at
+ ;; the root.
+ (if (= (match-beginning 0) 0)
+ (replace-match "./" t t entry 1)
+ (concat "./" entry)))
+ (t entry)))
+ (vc-call-backend backend 'ignore-completion-table root))))
+ (project--value-in-dir 'project-vc-ignores root)
+ (mapcar
+ (lambda (dir)
+ (concat dir "/"))
+ vc-directory-exclusion-list))))
+
+(defun project-combine-directories (&rest lists-of-dirs)
+ "Return a sorted and culled list of directory names.
+Appends the elements of LISTS-OF-DIRS together, removes
+non-existing directories, as well as directories a parent of
+whose is already in the list."
+ (let* ((dirs (sort
+ (mapcar
+ (lambda (dir)
+ (file-name-as-directory (expand-file-name dir)))
+ (apply #'append lists-of-dirs))
+ #'string<))
+ (ref dirs))
+ ;; Delete subdirectories from the list.
+ (while (cdr ref)
+ (if (string-prefix-p (car ref) (cadr ref))
+ (setcdr ref (cddr ref))
+ (setq ref (cdr ref))))
+ (cl-delete-if-not #'file-exists-p dirs)))
+
+(defun project-subtract-directories (files dirs)
+ "Return a list of elements from FILES that are outside of DIRS.
+DIRS must contain directory names."
+ ;; Sidestep the issue of expanded/abbreviated file names here.
+ (cl-set-difference files dirs :test #'file-in-directory-p))
+
+(defun project--value-in-dir (var dir)
+ (with-temp-buffer
+ (setq default-directory dir)
+ (let ((enable-local-variables :all))
+ (hack-dir-local-variables-non-file-buffer))
+ (symbol-value var)))
+
+
+;;; Project commands
+
+;;;###autoload
+(defvar project-prefix-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "!" 'project-shell-command)
+ (define-key map "&" 'project-async-shell-command)
+ (define-key map "f" 'project-find-file)
+ (define-key map "F" 'project-or-external-find-file)
+ (define-key map "b" 'project-switch-to-buffer)
+ (define-key map "s" 'project-shell)
+ (define-key map "d" 'project-dired)
+ (define-key map "v" 'project-vc-dir)
+ (define-key map "c" 'project-compile)
+ (define-key map "e" 'project-eshell)
+ (define-key map "k" 'project-kill-buffers)
+ (define-key map "p" 'project-switch-project)
+ (define-key map "g" 'project-find-regexp)
+ (define-key map "G" 'project-or-external-find-regexp)
+ (define-key map "r" 'project-query-replace-regexp)
+ (define-key map "x" 'project-execute-extended-command)
+ map)
+ "Keymap for project commands.")
+
+;;;###autoload (define-key ctl-x-map "p" project-prefix-map)
+
+;; We can't have these place-specific maps inherit from
+;; project-prefix-map because project--other-place-command needs to
+;; know which map the key binding came from, as if it came from one of
+;; these maps, we don't want to set display-buffer-overriding-action
+
+(defvar project-other-window-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-o" #'project-display-buffer)
+ map)
+ "Keymap for project commands that display buffers in other windows.")
+
+(defvar project-other-frame-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-o" #'project-display-buffer-other-frame)
+ map)
+ "Keymap for project commands that display buffers in other frames.")
+
+(defun project--other-place-command (action &optional map)
+ (let* ((key (read-key-sequence-vector nil t))
+ (place-cmd (lookup-key map key))
+ (generic-cmd (lookup-key project-prefix-map key))
+ (switch-to-buffer-obey-display-actions t)
+ (display-buffer-overriding-action (unless place-cmd action)))
+ (if-let ((cmd (or place-cmd generic-cmd)))
+ (call-interactively cmd)
+ (user-error "%s is undefined" (key-description key)))))
+
+;;;###autoload
+(defun project-other-window-command ()
+ "Run project command, displaying resultant buffer in another window.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-window-map}"
+ (interactive)
+ (project--other-place-command '((display-buffer-pop-up-window)
+ (inhibit-same-window . t))
+ project-other-window-map))
+
+;;;###autoload (define-key ctl-x-4-map "p" #'project-other-window-command)
+
+;;;###autoload
+(defun project-other-frame-command ()
+ "Run project command, displaying resultant buffer in another frame.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-frame-map}"
+ (interactive)
+ (project--other-place-command '((display-buffer-pop-up-frame))
+ project-other-frame-map))
+
+;;;###autoload (define-key ctl-x-5-map "p" #'project-other-frame-command)
+
+;;;###autoload
+(defun project-other-tab-command ()
+ "Run project command, displaying resultant buffer in a new tab.
+
+The following commands are available:
+
+\\{project-prefix-map}"
+ (interactive)
+ (project--other-place-command '((display-buffer-in-new-tab))))
+
+;;;###autoload
+(when (bound-and-true-p tab-prefix-map)
+ (define-key tab-prefix-map "p" #'project-other-tab-command))
+
+(declare-function grep-read-files "grep")
+(declare-function xref--show-xrefs "xref")
+(declare-function xref--find-ignores-arguments "xref")
+
+;;;###autoload
+(defun project-find-regexp (regexp)
+ "Find all matches for REGEXP in the current project's roots.
+With \\[universal-argument] prefix, you can specify the directory
+to search in, and the file name pattern to search for. The
+pattern may use abbreviations defined in `grep-files-aliases',
+e.g. entering `ch' is equivalent to `*.[ch]'. As whitespace
+triggers completion when entering a pattern, including it
+requires quoting, e.g. `\\[quoted-insert]<space>'."
+ (interactive (list (project--read-regexp)))
+ (require 'xref)
+ (require 'grep)
+ (let* ((caller-dir default-directory)
+ (pr (project-current t))
+ (default-directory (project-root pr))
+ (files
+ (if (not current-prefix-arg)
+ (project-files pr)
+ (let ((dir (read-directory-name "Base directory: "
+ caller-dir nil t)))
+ (project--files-in-directory dir
+ nil
+ (grep-read-files regexp))))))
+ (xref--show-xrefs
+ (apply-partially #'project--find-regexp-in-files regexp files)
+ nil)))
+
+(defun project--dir-ignores (project dir)
+ (let ((root (project-root project)))
+ (if (not (file-in-directory-p dir root))
+ (project-ignores nil nil) ;The defaults.
+ (let ((ignores (project-ignores project root)))
+ (if (file-equal-p root dir)
+ ignores
+ ;; FIXME: Update the "rooted" ignores to relate to DIR instead.
+ (cl-delete-if (lambda (str) (string-prefix-p "./" str))
+ ignores))))))
+
+;;;###autoload
+(defun project-or-external-find-regexp (regexp)
+ "Find all matches for REGEXP in the project roots or external roots.
+With \\[universal-argument] prefix, you can specify the file name
+pattern to search for."
+ (interactive (list (project--read-regexp)))
+ (require 'xref)
+ (let* ((pr (project-current t))
+ (default-directory (project-root pr))
+ (files
+ (project-files pr (cons
+ (project-root pr)
+ (project-external-roots pr)))))
+ (xref--show-xrefs
+ (apply-partially #'project--find-regexp-in-files regexp files)
+ nil)))
+
+(defun project--find-regexp-in-files (regexp files)
+ (unless files
+ (user-error "Empty file list"))
+ (let ((xrefs (xref-matches-in-files regexp files)))
+ (unless xrefs
+ (user-error "No matches for: %s" regexp))
+ xrefs))
+
+(defvar project-regexp-history-variable 'grep-regexp-history)
+
+(defun project--read-regexp ()
+ (let ((sym (thing-at-point 'symbol t)))
+ (read-regexp "Find regexp" (and sym (regexp-quote sym))
+ project-regexp-history-variable)))
+
+;;;###autoload
+(defun project-find-file ()
+ "Visit a file (with completion) in the current project.
+
+The completion default is the filename at point, determined by
+`thing-at-point' (whether such file exists or not)."
+ (interactive)
+ (let* ((pr (project-current t))
+ (dirs (list (project-root pr))))
+ (project-find-file-in (thing-at-point 'filename) dirs pr)))
+
+;;;###autoload
+(defun project-or-external-find-file ()
+ "Visit a file (with completion) in the current project or external roots.
+
+The completion default is the filename at point, determined by
+`thing-at-point' (whether such file exists or not)."
+ (interactive)
+ (let* ((pr (project-current t))
+ (dirs (cons
+ (project-root pr)
+ (project-external-roots pr))))
+ (project-find-file-in (thing-at-point 'filename) dirs pr)))
+
+(defcustom project-read-file-name-function #'project--read-file-cpd-relative
+ "Function to call to read a file name from a list.
+For the arguments list, see `project--read-file-cpd-relative'."
+ :type '(choice (const :tag "Read with completion from relative names"
+ project--read-file-cpd-relative)
+ (const :tag "Read with completion from absolute names"
+ project--read-file-absolute)
+ (function :tag "Custom function" nil))
+ :group 'project
+ :version "27.1")
+
+(defun project--read-file-cpd-relative (prompt
+ all-files &optional predicate
+ hist default)
+ "Read a file name, prompting with PROMPT.
+ALL-FILES is a list of possible file name completions.
+PREDICATE, HIST, and DEFAULT have the same meaning as in
+`completing-read'."
+ (let* ((common-parent-directory
+ (let ((common-prefix (try-completion "" all-files)))
+ (if (> (length common-prefix) 0)
+ (file-name-directory common-prefix))))
+ (cpd-length (length common-parent-directory))
+ (prompt (if (zerop cpd-length)
+ prompt
+ (concat prompt (format " in %s" common-parent-directory))))
+ (substrings (mapcar (lambda (s) (substring s cpd-length)) all-files))
+ (new-collection (project--file-completion-table substrings))
+ (res (project--completing-read-strict prompt
+ new-collection
+ predicate
+ hist default)))
+ (concat common-parent-directory res)))
+
+(defun project--read-file-absolute (prompt
+ all-files &optional predicate
+ hist default)
+ (project--completing-read-strict prompt
+ (project--file-completion-table all-files)
+ predicate
+ hist default))
+
+(defun project-find-file-in (filename dirs project)
+ "Complete FILENAME in DIRS in PROJECT and visit the result."
+ (let* ((all-files (project-files project dirs))
+ (completion-ignore-case read-file-name-completion-ignore-case)
+ (file (funcall project-read-file-name-function
+ "Find file" all-files nil nil
+ filename)))
+ (if (string= file "")
+ (user-error "You didn't specify the file")
+ (find-file file))))
+
+(defun project--completing-read-strict (prompt
+ collection &optional predicate
+ hist default)
+ ;; Tried both expanding the default before showing the prompt, and
+ ;; removing it when it has no matches. Neither seems natural
+ ;; enough. Removal is confusing; early expansion makes the prompt
+ ;; too long.
+ (let* ((new-prompt (if (and default (not (string-equal default "")))
+ (format "%s (default %s): " prompt default)
+ (format "%s: " prompt)))
+ (res (completing-read new-prompt
+ collection predicate t
+ nil ;; initial-input
+ hist default)))
+ (when (and (equal res default)
+ (not (test-completion res collection predicate)))
+ (setq res
+ (completing-read (format "%s: " prompt)
+ collection predicate t res hist nil)))
+ res))
+
+;;;###autoload
+(defun project-dired ()
+ "Start Dired in the current project's root."
+ (interactive)
+ (dired (project-root (project-current t))))
+
+;;;###autoload
+(defun project-vc-dir ()
+ "Run VC-Dir in the current project's root."
+ (interactive)
+ (vc-dir (project-root (project-current t))))
+
+;;;###autoload
+(defun project-shell ()
+ "Start an inferior shell in the current project's root directory.
+If a buffer already exists for running a shell in the project's root,
+switch to it. Otherwise, create a new shell buffer.
+With \\[universal-argument] prefix arg, create a new inferior shell buffer even
+if one already exists."
+ (interactive)
+ (let* ((default-directory (project-root (project-current t)))
+ (default-project-shell-name (project-prefixed-buffer-name "shell"))
+ (shell-buffer (get-buffer default-project-shell-name)))
+ (if (and shell-buffer (not current-prefix-arg))
+ (pop-to-buffer-same-window shell-buffer)
+ (shell (generate-new-buffer-name default-project-shell-name)))))
+
+;;;###autoload
+(defun project-eshell ()
+ "Start Eshell in the current project's root directory.
+If a buffer already exists for running Eshell in the project's root,
+switch to it. Otherwise, create a new Eshell buffer.
+With \\[universal-argument] prefix arg, create a new Eshell buffer even
+if one already exists."
+ (interactive)
+ (defvar eshell-buffer-name)
+ (let* ((default-directory (project-root (project-current t)))
+ (eshell-buffer-name (project-prefixed-buffer-name "eshell"))
+ (eshell-buffer (get-buffer eshell-buffer-name)))
+ (if (and eshell-buffer (not current-prefix-arg))
+ (pop-to-buffer-same-window eshell-buffer)
+ (eshell t))))
+
+;;;###autoload
+(defun project-async-shell-command ()
+ "Run `async-shell-command' in the current project's root directory."
+ (declare (interactive-only async-shell-command))
+ (interactive)
+ (let ((default-directory (project-root (project-current t))))
+ (call-interactively #'async-shell-command)))
+
+;;;###autoload
+(defun project-shell-command ()
+ "Run `shell-command' in the current project's root directory."
+ (declare (interactive-only shell-command))
+ (interactive)
+ (let ((default-directory (project-root (project-current t))))
+ (call-interactively #'shell-command)))
+
+(declare-function fileloop-continue "fileloop" ())
+
+;;;###autoload
+(defun project-search (regexp)
+ "Search for REGEXP in all the files of the project.
+Stops when a match is found.
+To continue searching for the next match, use the
+command \\[fileloop-continue]."
+ (interactive "sSearch (regexp): ")
+ (fileloop-initialize-search
+ regexp (project-files (project-current t)) 'default)
+ (fileloop-continue))
+
+;;;###autoload
+(defun project-query-replace-regexp (from to)
+ "Query-replace REGEXP in all the files of the project.
+Stops when a match is found and prompts for whether to replace it.
+If you exit the query-replace, you can later continue the query-replace
+loop using the command \\[fileloop-continue]."
+ (interactive
+ (pcase-let ((`(,from ,to)
+ (query-replace-read-args "Query replace (regexp)" t t)))
+ (list from to)))
+ (fileloop-initialize-replace
+ from to (project-files (project-current t)) 'default)
+ (fileloop-continue))
+
+(defvar compilation-read-command)
+(declare-function compilation-read-command "compile")
+
+(defun project-prefixed-buffer-name (mode)
+ (concat "*"
+ (file-name-nondirectory
+ (directory-file-name default-directory))
+ "-"
+ (downcase mode)
+ "*"))
+
+(defcustom project-compilation-buffer-name-function nil
+ "Function to compute the name of a project compilation buffer.
+If non-nil, it overrides `compilation-buffer-name-function' for
+`project-compile'."
+ :version "28.1"
+ :group 'project
+ :type '(choice (const :tag "Default" nil)
+ (const :tag "Prefixed with root directory name"
+ project-prefixed-buffer-name)
+ (function :tag "Custom function")))
+
+;;;###autoload
+(defun project-compile ()
+ "Run `compile' in the project root."
+ (declare (interactive-only compile))
+ (interactive)
+ (let ((default-directory (project-root (project-current t)))
+ (compilation-buffer-name-function
+ (or project-compilation-buffer-name-function
+ compilation-buffer-name-function)))
+ (call-interactively #'compile)))
+
+(defun project--read-project-buffer ()
+ (let* ((pr (project-current t))
+ (current-buffer (current-buffer))
+ (other-buffer (other-buffer current-buffer))
+ (other-name (buffer-name other-buffer))
+ (predicate
+ (lambda (buffer)
+ ;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist.
+ (and (cdr buffer)
+ (equal pr
+ (with-current-buffer (cdr buffer)
+ (project-current)))))))
+ (read-buffer
+ "Switch to buffer: "
+ (when (funcall predicate (cons other-name other-buffer))
+ other-name)
+ nil
+ predicate)))
+
+;;;###autoload
+(defun project-switch-to-buffer (buffer-or-name)
+ "Display buffer BUFFER-OR-NAME in the selected window.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical."
+ (interactive (list (project--read-project-buffer)))
+ (switch-to-buffer buffer-or-name))
+
+;;;###autoload
+(defun project-display-buffer (buffer-or-name)
+ "Display BUFFER-OR-NAME in some window, without selecting it.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+This function uses `display-buffer' as a subroutine, which see
+for how it is determined where the buffer will be displayed."
+ (interactive (list (project--read-project-buffer)))
+ (display-buffer buffer-or-name))
+
+;;;###autoload
+(defun project-display-buffer-other-frame (buffer-or-name)
+ "Display BUFFER-OR-NAME preferably in another frame.
+When called interactively, prompts for a buffer belonging to the
+current project. Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+This function uses `display-buffer-other-frame' as a subroutine,
+which see for how it is determined where the buffer will be
+displayed."
+ (interactive (list (project--read-project-buffer)))
+ (display-buffer-other-frame buffer-or-name))
+
+(defcustom project-kill-buffer-conditions
+ '(buffer-file-name ; All file-visiting buffers are included.
+ ;; Most of the temp buffers in the background:
+ (major-mode . fundamental-mode)
+ ;; non-text buffer such as xref, occur, vc, log, ...
+ (and (derived-mode . special-mode)
+ (not (major-mode . help-mode)))
+ (derived-mode . compilation-mode)
+ (derived-mode . dired-mode)
+ (derived-mode . diff-mode))
+ "List of conditions to kill buffers related to a project.
+This list is used by `project-kill-buffers'.
+Each condition is either:
+- a regular expression, to match a buffer name,
+- a predicate function that takes a buffer object as argument
+ and returns non-nil if the buffer should be killed,
+- a cons-cell, where the car describes how to interpret the cdr.
+ The car can be one of the following:
+ * `major-mode': the buffer is killed if the buffer's major
+ mode is eq to the cons-cell's cdr
+ * `derived-mode': the buffer is killed if the buffer's major
+ mode is derived from the major mode denoted by the cons-cell's
+ cdr
+ * `not': the cdr is interpreted as a negation of a condition.
+ * `and': the cdr is a list of recursive conditions, that all have
+ to be met.
+ * `or': the cdr is a list of recursive conditions, of which at
+ least one has to be met.
+
+If any of these conditions are satisfied for a buffer in the
+current project, it will be killed."
+ :type '(repeat (choice regexp function symbol
+ (cons :tag "Major mode"
+ (const major-mode) symbol)
+ (cons :tag "Derived mode"
+ (const derived-mode) symbol)
+ (cons :tag "Negation"
+ (const not) sexp)
+ (cons :tag "Conjunction"
+ (const and) sexp)
+ (cons :tag "Disjunction"
+ (const or) sexp)))
+ :version "28.1"
+ :group 'project
+ :package-version '(project . "0.6.0"))
+
+(defun project--buffer-list (pr)
+ "Return the list of all buffers in project PR."
+ (let (bufs)
+ (dolist (buf (buffer-list))
+ (when (equal pr
+ (with-current-buffer buf
+ (project-current)))
+ (push buf bufs)))
+ (nreverse bufs)))
+
+(defun project--kill-buffer-check (buf conditions)
+ "Check if buffer BUF matches any element of the list CONDITIONS.
+See `project-kill-buffer-conditions' for more details on the form
+of CONDITIONS."
+ (catch 'kill
+ (dolist (c conditions)
+ (when (cond
+ ((stringp c)
+ (string-match-p c (buffer-name buf)))
+ ((symbolp c)
+ (funcall c buf))
+ ((eq (car-safe c) 'major-mode)
+ (eq (buffer-local-value 'major-mode buf)
+ (cdr c)))
+ ((eq (car-safe c) 'derived-mode)
+ (provided-mode-derived-p
+ (buffer-local-value 'major-mode buf)
+ (cdr c)))
+ ((eq (car-safe c) 'not)
+ (not (project--kill-buffer-check buf (cdr c))))
+ ((eq (car-safe c) 'or)
+ (project--kill-buffer-check buf (cdr c)))
+ ((eq (car-safe c) 'and)
+ (seq-every-p
+ (apply-partially #'project--kill-buffer-check
+ buf)
+ (mapcar #'list (cdr c)))))
+ (throw 'kill t)))))
+
+(defun project--buffers-to-kill (pr)
+ "Return list of buffers in project PR to kill.
+What buffers should or should not be killed is described
+in `project-kill-buffer-conditions'."
+ (let (bufs)
+ (dolist (buf (project--buffer-list pr))
+ (when (project--kill-buffer-check buf project-kill-buffer-conditions)
+ (push buf bufs)))
+ bufs))
+
+;;;###autoload
+(defun project-kill-buffers (&optional no-confirm)
+ "Kill the buffers belonging to the current project.
+Two buffers belong to the same project if their project
+instances, as reported by `project-current' in each buffer, are
+identical. Only the buffers that match a condition in
+`project-kill-buffer-conditions' will be killed. If NO-CONFIRM
+is non-nil, the command will not ask the user for confirmation.
+NO-CONFIRM is always nil when the command is invoked
+interactively."
+ (interactive)
+ (let* ((pr (project-current t))
+ (bufs (project--buffers-to-kill pr)))
+ (cond (no-confirm
+ (mapc #'kill-buffer bufs))
+ ((null bufs)
+ (message "No buffers to kill"))
+ ((yes-or-no-p (format "Kill %d buffers in %s? "
+ (length bufs)
+ (project-root pr)))
+ (mapc #'kill-buffer bufs)))))
+
+
+;;; Project list
+
+(defcustom project-list-file (locate-user-emacs-file "projects")
+ "File in which to save the list of known projects."
+ :type 'file
+ :version "28.1"
+ :group 'project)
+
+(defvar project--list 'unset
+ "List structure containing root directories of known projects.
+With some possible metadata (to be decided).")
+
+(defun project--read-project-list ()
+ "Initialize `project--list' using contents of `project-list-file'."
+ (let ((filename project-list-file))
+ (setq project--list
+ (when (file-exists-p filename)
+ (with-temp-buffer
+ (insert-file-contents filename)
+ (read (current-buffer)))))
+ (unless (seq-every-p
+ (lambda (elt) (stringp (car-safe elt)))
+ project--list)
+ (warn "Contents of %s are in wrong format, resetting"
+ project-list-file)
+ (setq project--list nil))))
+
+(defun project--ensure-read-project-list ()
+ "Initialize `project--list' if it isn't already initialized."
+ (when (eq project--list 'unset)
+ (project--read-project-list)))
+
+(defun project--write-project-list ()
+ "Save `project--list' in `project-list-file'."
+ (let ((filename project-list-file))
+ (with-temp-buffer
+ (insert ";;; -*- lisp-data -*-\n")
+ (let ((print-length nil)
+ (print-level nil))
+ (pp project--list (current-buffer)))
+ (write-region nil nil filename nil 'silent))))
+
+;;;###autoload
+(defun project-remember-project (pr)
+ "Add project PR to the front of the project list.
+Save the result in `project-list-file' if the list of projects has changed."
+ (project--ensure-read-project-list)
+ (let ((dir (project-root pr)))
+ (unless (equal (caar project--list) dir)
+ (dolist (ent project--list)
+ (when (equal dir (car ent))
+ (setq project--list (delq ent project--list))))
+ (push (list dir) project--list)
+ (project--write-project-list))))
+
+(defun project--remove-from-project-list (project-root report-message)
+ "Remove directory PROJECT-ROOT of a missing project from the project list.
+If the directory was in the list before the removal, save the
+result in `project-list-file'. Announce the project's removal
+from the list using REPORT-MESSAGE, which is a format string
+passed to `message' as its first argument."
+ (project--ensure-read-project-list)
+ (when-let ((ent (assoc project-root project--list)))
+ (setq project--list (delq ent project--list))
+ (message report-message project-root)
+ (project--write-project-list)))
+
+;;;###autoload
+(defun project-remove-known-project (project-root)
+ "Remove directory PROJECT-ROOT from the project list.
+PROJECT-ROOT is the root directory of a known project listed in
+the project list."
+ (interactive (list (project-prompt-project-dir)))
+ (project--remove-from-project-list
+ project-root "Project `%s' removed from known projects"))
+
+(defun project-prompt-project-dir ()
+ "Prompt the user for a directory that is one of the known project roots.
+The project is chosen among projects known from the project list,
+see `project-list-file'.
+It's also possible to enter an arbitrary directory not in the list."
+ (project--ensure-read-project-list)
+ (let* ((dir-choice "... (choose a dir)")
+ (choices
+ ;; XXX: Just using this for the category (for the substring
+ ;; completion style).
+ (project--file-completion-table
+ (append project--list `(,dir-choice))))
+ (pr-dir (completing-read "Select project: " choices nil t)))
+ (if (equal pr-dir dir-choice)
+ (read-directory-name "Select directory: " default-directory nil t)
+ pr-dir)))
+
+;;;###autoload
+(defun project-known-project-roots ()
+ "Return the list of root directories of all known projects."
+ (project--ensure-read-project-list)
+ (mapcar #'car project--list))
+
+;;;###autoload
+(defun project-execute-extended-command ()
+ "Execute an extended command in project root."
+ (declare (interactive-only command-execute))
+ (interactive)
+ (let ((default-directory (project-root (project-current t))))
+ (call-interactively #'execute-extended-command)))
+
+
+;;; Project switching
+
+(defcustom project-switch-commands
+ '((project-find-file "Find file")
+ (project-find-regexp "Find regexp")
+ (project-dired "Dired")
+ (project-vc-dir "VC-Dir")
+ (project-eshell "Eshell"))
+ "Alist mapping commands to descriptions.
+Used by `project-switch-project' to construct a dispatch menu of
+commands available upon \"switching\" to another project.
+
+Each element is of the form (COMMAND LABEL &optional KEY) where
+COMMAND is the command to run when KEY is pressed. LABEL is used
+to distinguish the menu entries in the dispatch menu. If KEY is
+absent, COMMAND must be bound in `project-prefix-map', and the
+key is looked up in that map."
+ :version "28.1"
+ :group 'project
+ :package-version '(project . "0.6.0")
+ :type '(repeat
+ (list
+ (symbol :tag "Command")
+ (string :tag "Label")
+ (choice :tag "Key to press"
+ (const :tag "Infer from the keymap" nil)
+ (character :tag "Explicit key")))))
+
+(defcustom project-switch-use-entire-map nil
+ "Make `project-switch-project' use entire `project-prefix-map'.
+If nil, `project-switch-project' will only recognize commands
+listed in `project-switch-commands' and signal an error when
+others are invoked. Otherwise, all keys in `project-prefix-map'
+are legal even if they aren't listed in the dispatch menu."
+ :type 'boolean
+ :group 'project
+ :version "28.1")
+
+(defun project--keymap-prompt ()
+ "Return a prompt for the project switching dispatch menu."
+ (mapconcat
+ (pcase-lambda (`(,cmd ,label ,key))
+ (when (characterp cmd) ; Old format, apparently user-customized.
+ (let ((tmp cmd))
+ ;; TODO: Add a deprecation warning, probably.
+ (setq cmd key
+ key tmp)))
+ (let ((key (if key
+ (vector key)
+ (where-is-internal cmd (list project-prefix-map) t))))
+ (format "[%s] %s"
+ (propertize (key-description key) 'face 'bold)
+ label)))
+ project-switch-commands
+ " "))
+
+;;;###autoload
+(defun project-switch-project (dir)
+ "\"Switch\" to another project by running an Emacs command.
+The available commands are presented as a dispatch menu
+made from `project-switch-commands'.
+
+When called in a program, it will use the project corresponding
+to directory DIR."
+ (interactive (list (project-prompt-project-dir)))
+ (let* ((commands-menu
+ (mapcar
+ (lambda (row)
+ (if (characterp (car row))
+ ;; Deprecated format.
+ ;; XXX: Add a warning about it?
+ (reverse row)
+ row))
+ project-switch-commands))
+ (commands-map
+ (let ((temp-map (make-sparse-keymap)))
+ (set-keymap-parent temp-map project-prefix-map)
+ (dolist (row commands-menu temp-map)
+ (when-let ((cmd (nth 0 row))
+ (keychar (nth 2 row)))
+ (define-key temp-map (vector keychar) cmd)))))
+ command)
+ (while (not command)
+ (let ((overriding-local-map commands-map)
+ (choice (read-key-sequence (project--keymap-prompt))))
+ (when (setq command (lookup-key commands-map choice))
+ (unless (or project-switch-use-entire-map
+ (assq command commands-menu))
+ ;; TODO: Add some hint to the prompt, like "key not
+ ;; recognized" or something.
+ (setq command nil)))
+ (let ((global-command (lookup-key (current-global-map) choice)))
+ (when (memq global-command
+ '(keyboard-quit keyboard-escape-quit))
+ (call-interactively global-command)))))
+ (let ((default-directory dir)
+ (project-current-inhibit-prompt t))
+ (call-interactively command))))
+
+(provide 'project)
+;;; project.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-autoloads.el b/emacs.d/elpa/rustic-20210609.1900/rustic-autoloads.el
new file mode 100644
index 0000000..97b6ec1
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-autoloads.el
@@ -0,0 +1,382 @@
+;;; rustic-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "rustic" "rustic.el" (0 0 0 0))
+;;; Generated autoloads from rustic.el
+
+(autoload 'rustic-mode "rustic" "\
+Major mode for Rust code.
+
+\\{rustic-mode-map}
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.rs\\'" . rustic-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-babel" "rustic-babel.el" (0 0 0 0))
+;;; Generated autoloads from rustic-babel.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-babel" '("cargo-toml-dependencies" "crate-dependencies" "org-babel-execute:rust" "rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-cargo" "rustic-cargo.el" (0 0 0 0))
+;;; Generated autoloads from rustic-cargo.el
+
+(autoload 'rustic-cargo-clippy-run "rustic-cargo" "\
+Run `cargo clippy' with optional ARGS.
+
+\(fn &optional ARGS)" t nil)
+
+(autoload 'rustic-cargo-clippy "rustic-cargo" "\
+Run 'cargo clippy'.
+
+If ARG is not nil, use value as argument and store it in `rustic-clippy-arguments'.
+When calling this function from `rustic-popup-mode', always use the value of
+`rustic-clippy-arguments'.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-cargo-clippy-rerun "rustic-cargo" "\
+Run 'cargo clippy' with `rustic-clippy-arguments'." t nil)
+
+(autoload 'rustic-cargo-test-run "rustic-cargo" "\
+Start compilation process for 'cargo test' with optional TEST-ARGS.
+
+\(fn &optional TEST-ARGS)" t nil)
+
+(autoload 'rustic-cargo-test "rustic-cargo" "\
+Run 'cargo test'.
+
+If ARG is not nil, use value as argument and store it in `rustic-test-arguments'.
+When calling this function from `rustic-popup-mode', always use the value of
+`rustic-test-arguments'.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-cargo-test-rerun "rustic-cargo" "\
+Run 'cargo test' with `rustic-test-arguments'." t nil)
+
+(autoload 'rustic-cargo-current-test "rustic-cargo" "\
+Run 'cargo test' for the test near point." t nil)
+
+(autoload 'rustic-cargo-outdated "rustic-cargo" "\
+Use 'cargo outdated' to list outdated packages in `tabulated-list-mode'.
+Execute process in PATH.
+
+\(fn &optional PATH)" t nil)
+
+(autoload 'rustic-cargo-reload-outdated "rustic-cargo" "\
+Update list of outdated packages." t nil)
+
+(autoload 'rustic-cargo-mark-upgrade "rustic-cargo" "\
+Mark an upgradable package." t nil)
+
+(autoload 'rustic-cargo-mark-all-upgrades "rustic-cargo" "\
+Mark all upgradable packages in the Package Menu." t nil)
+
+(autoload 'rustic-cargo-menu-mark-unmark "rustic-cargo" "\
+Clear any marks on a package." t nil)
+
+(autoload 'rustic-cargo-upgrade-execute "rustic-cargo" "\
+Perform marked menu actions." t nil)
+
+(autoload 'rustic-cargo-new "rustic-cargo" "\
+Run 'cargo new' to start a new package in the path specified by PROJECT-PATH.
+If BIN is not nil, create a binary application, otherwise a library.
+
+\(fn PROJECT-PATH &optional BIN)" t nil)
+
+(autoload 'rustic-cargo-init "rustic-cargo" "\
+Run 'cargo init' to initialize a directory in the path specified by PROJECT-PATH.
+If BIN is not nil, create a binary application, otherwise a library.
+
+\(fn PROJECT-PATH &optional BIN)" t nil)
+
+(autoload 'rustic-cargo-build "rustic-cargo" "\
+Run 'cargo build' for the current project." t nil)
+
+(autoload 'rustic-cargo-run "rustic-cargo" "\
+Run 'cargo run' for the current project.
+If running with prefix command `C-u', read whole command from minibuffer.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-cargo-clean "rustic-cargo" "\
+Run 'cargo clean' for the current project." t nil)
+
+(autoload 'rustic-cargo-check "rustic-cargo" "\
+Run 'cargo check' for the current project." t nil)
+
+(autoload 'rustic-cargo-bench "rustic-cargo" "\
+Run 'cargo bench' for the current project." t nil)
+
+(autoload 'rustic-cargo-build-doc "rustic-cargo" "\
+Build the documentation for the current project." t nil)
+
+(autoload 'rustic-cargo-doc "rustic-cargo" "\
+Open the documentation for the current project in a browser.
+The documentation is built if necessary." t nil)
+
+(autoload 'rustic-cargo-add "rustic-cargo" "\
+Add crate to Cargo.toml using 'cargo add'.
+If running with prefix command `C-u', read whole command from minibuffer.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-cargo-rm "rustic-cargo" "\
+Remove crate from Cargo.toml using 'cargo rm'.
+If running with prefix command `C-u', read whole command from minibuffer.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-cargo-upgrade "rustic-cargo" "\
+Upgrade dependencies as specified in the local manifest file using 'cargo upgrade'.
+If running with prefix command `C-u', read whole command from minibuffer.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-cargo" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-compile" "rustic-compile.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from rustic-compile.el
+
+(autoload 'rustic-compile "rustic-compile" "\
+Compile rust project.
+
+If `compilation-read-command' is non-nil or if called with prefix
+argument ARG then read the command in the minibuffer. Otherwise
+use `rustic-compile-command'.
+
+In either store the used command in `compilation-arguments'.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'rustic-recompile "rustic-compile" "\
+Re-compile the program using `compilation-arguments'." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-compile" '("rust")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-doc" "rustic-doc.el" (0 0 0 0))
+;;; Generated autoloads from rustic-doc.el
+
+(autoload 'rustic-doc-dumb-search "rustic-doc" "\
+Search all projects and std for SEARCH-TERM.
+Use this when `rustic-doc-search' does not find what you're looking for.
+Add `universal-argument' to only search level 1 headers.
+See `rustic-doc-search' for more information.
+
+\(fn SEARCH-TERM)" t nil)
+
+(autoload 'rustic-doc-search "rustic-doc" "\
+Search the rust documentation for SEARCH-TERM.
+Only searches in headers (structs, functions, traits, enums, etc)
+to limit the number of results.
+To limit search results to only level 1 headers, add `universal-argument'
+Level 1 headers are things like struct or enum names.
+if ROOT is non-nil the search is performed from the root dir.
+This function tries to be smart and limits the search results
+as much as possible. If it ends up being so smart that
+it doesn't manage to find what you're looking for, try `rustic-doc-dumb-search'.
+
+\(fn SEARCH-TERM &optional ROOT)" t nil)
+
+(autoload 'rustic-doc-convert-current-package "rustic-doc" "\
+Convert the documentation for a project and its dependencies." t nil)
+
+(autoload 'rustic-doc-setup "rustic-doc" "\
+Setup or update rustic-doc filter and convert script. Convert std." t nil)
+
+(autoload 'rustic-doc-mode "rustic-doc" "\
+Convert rust html docs to .org, and browse the converted docs.
+
+If called interactively, enable Rustic-Doc mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is `toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-doc" '("rustic-doc-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-flycheck" "rustic-flycheck.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from rustic-flycheck.el
+
+(autoload 'rustic-flycheck-setup "rustic-flycheck" "\
+Setup Rust in Flycheck.
+
+If the current file is part of a Cargo project, configure
+Flycheck according to the Cargo project layout." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-flycheck" '("rustic-flycheck-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-interaction" "rustic-interaction.el"
+;;;;;; (0 0 0 0))
+;;; Generated autoloads from rustic-interaction.el
+
+(autoload 'rustic-indent-line "rustic-interaction" nil t nil)
+
+(autoload 'rustic-promote-module-into-dir "rustic-interaction" "\
+Promote the module file visited by the current buffer into its own directory.
+
+For example, if the current buffer is visiting the file `foo.rs',
+then this function creates the directory `foo' and renames the
+file to `foo/mod.rs'. The current buffer will be updated to
+visit the new file." t nil)
+
+(autoload 'rustic-open-dependency-file "rustic-interaction" "\
+Open the 'Cargo.toml' file at the project root if the current buffer is
+visiting a project." t nil)
+
+(autoload 'rustic-beginning-of-defun "rustic-interaction" "\
+Move backward to the beginning of the current defun.
+
+With ARG, move backward multiple defuns. Negative ARG means
+move forward.
+
+This is written mainly to be used as `beginning-of-defun-function' for Rust.
+Don't move to the beginning of the line. `beginning-of-defun',
+which calls this, does that afterwards.
+
+\(fn &optional ARG REGEX)" t nil)
+
+(autoload 'rustic-end-of-defun "rustic-interaction" "\
+Move forward to the next end of defun.
+
+With argument, do it that many times.
+Negative argument -N means move back to Nth preceding end of defun.
+
+Assume that this is called after beginning-of-defun. So point is
+at the beginning of the defun body.
+
+This is written mainly to be used as `end-of-defun-function' for Rust." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-interaction" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-lsp" "rustic-lsp.el" (0 0 0 0))
+;;; Generated autoloads from rustic-lsp.el
+
+(autoload 'rustic-analyzer-macro-expand "rustic-lsp" "\
+Default method for displaying macro expansion results.
+
+\(fn RESULT)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-lsp" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-playpen" "rustic-playpen.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from rustic-playpen.el
+
+(autoload 'rustic-playpen "rustic-playpen" "\
+Create a shareable URL for the contents of the current region,
+src-block or buffer on the Rust playpen.
+
+\(fn BEGIN END)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-playpen" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-popup" "rustic-popup.el" (0 0 0 0))
+;;; Generated autoloads from rustic-popup.el
+
+(autoload 'rustic-popup "rustic-popup" "\
+Setup popup.
+If directory is not in a rust project call `read-directory-name'." t nil)
+
+(autoload 'rustic-popup-invoke-popup-action "rustic-popup" "\
+Execute commands which are listed in `rustic-popup-commands'.
+
+\(fn EVENT)" t nil)
+
+(autoload 'rustic-popup-default-action "rustic-popup" "\
+Change backtrace and `compilation-arguments' when executed on
+corresponding line." t nil)
+
+(autoload 'rustic-popup-cargo-command-help "rustic-popup" "\
+Display help buffer for cargo command at point." t nil)
+
+(autoload 'rustic-popup-kill-help-buffer "rustic-popup" "\
+Kill popup help buffer and switch to popup buffer." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-popup" '("rustic-popup-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-racer" "rustic-racer.el" (0 0 0 0))
+;;; Generated autoloads from rustic-racer.el
+
+(autoload 'rustic-racer-describe "rustic-racer" "\
+Show a *Racer Help* buffer for the function or type at point." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-racer" '("racer-src-button" "rustic-racer-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-rustfix" "rustic-rustfix.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from rustic-rustfix.el
+
+(autoload 'rustic-rustfix "rustic-rustfix" "\
+Run 'cargo fix'." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-rustfix" '("rustic-rustfix-")))
+
+;;;***
+
+;;;### (autoloads nil "rustic-rustfmt" "rustic-rustfmt.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from rustic-rustfmt.el
+
+(autoload 'rustic-cargo-fmt "rustic-rustfmt" "\
+Use rustfmt via cargo." t nil)
+
+(autoload 'rustic-format-buffer "rustic-rustfmt" "\
+Format the current buffer using rustfmt.
+
+Provide optional argument NO-STDIN for `rustic-before-save-hook' since there
+were issues when using stdin for formatting." t nil)
+
+(autoload 'rustic-format-file "rustic-rustfmt" "\
+Unlike `rustic-format-buffer' format file directly and revert the buffer.
+
+\(fn &optional FILE)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rustic-rustfmt" '("rustic-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("rustic-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; rustic-autoloads.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-babel.el b/emacs.d/elpa/rustic-20210609.1900/rustic-babel.el
new file mode 100644
index 0000000..2a6dbb0
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-babel.el
@@ -0,0 +1,288 @@
+;;; rustic-babel.el --- Org babel facilities for cargo -*-lexical-binding: t-*-
+
+;;; Code:
+
+(require 'org)
+(require 'org-element)
+(require 'ob)
+(require 'ob-eval)
+(require 'ob-ref)
+(require 'ob-core)
+
+(require 'rustic-rustfmt)
+
+;; FIXME This variable doesn't exist in noninteractive emacs sessions,
+;; which probably means that it is internal and we shouldn't use it.
+(defvar org-babel-temporary-directory)
+
+(defvar rustic-info nil)
+
+(add-to-list 'org-src-lang-modes '("rust" . rustic))
+(add-to-list 'org-babel-tangle-lang-exts '("rustic" . "rs"))
+(defalias 'org-babel-execute:rust #'org-babel-execute:rustic)
+
+(defcustom rustic-babel-display-compilation-buffer nil
+ "Whether to display compilation buffer."
+ :type 'boolean
+ :group 'rustic-babel)
+
+(defcustom rustic-babel-format-src-block t
+ "Whether to format a src block automatically after successful execution."
+ :type 'boolean
+ :group 'rustic-babel)
+
+(defvar rustic-babel-buffer-name '((:default . "*rust-babel*")))
+
+(defvar rustic-babel-process-name "rustic-babel-process"
+ "Process name for org-babel rust compilation processes.")
+
+(defvar rustic-babel-compilation-buffer-name "*rustic-babel-compilation-buffer*"
+ "Buffer name for org-babel rust compilation process buffers.")
+
+(defvar rustic-babel-dir nil
+ "Holds the latest rust babel project directory.")
+
+(defvar rustic-babel-src-location nil
+ "Marker, holding location of last evaluated src block.")
+
+(defvar rustic-babel-params nil
+ "Babel parameters.")
+
+(defvar rustic-babel-spinner nil)
+
+(defun rustic-babel-eval (dir)
+ "Start a rust babel compilation process in directory DIR."
+ (let* ((err-buff (get-buffer-create rustic-babel-compilation-buffer-name))
+ (default-directory dir)
+ (params '("cargo" "build" "--quiet"))
+ (inhibit-read-only t))
+ (rustic-compilation-setup-buffer err-buff dir 'rustic-compilation-mode)
+ (when rustic-babel-display-compilation-buffer
+ (display-buffer err-buff))
+ (rustic-make-process
+ :name rustic-babel-process-name
+ :buffer err-buff
+ :command params
+ :filter #'rustic-compilation-filter
+ :sentinel #'rustic-babel-build-sentinel)))
+
+(defun rustic-babel-build-sentinel (proc _output)
+ "Sentinel for rust babel compilation process PROC.
+If `rustic-babel-format-src-block' is t, format src-block after successful
+execution with rustfmt."
+ (let ((proc-buffer (process-buffer proc))
+ (inhibit-read-only t))
+ (if (zerop (process-exit-status proc))
+ (let* ((default-directory rustic-babel-dir))
+ ;; format babel block
+ (when rustic-babel-format-src-block
+ (let ((babel-body
+ (org-element-property :value (org-element-at-point)))
+ (proc
+ (make-process :name "rustic-babel-format"
+ :buffer "rustic-babel-format-buffer"
+ :command `(,rustic-rustfmt-bin
+ ,@(rustic-compute-rustfmt-args))
+ :filter #'rustic-compilation-filter
+ :sentinel #'rustic-babel-format-sentinel)))
+ (while (not (process-live-p proc))
+ (sleep-for 0.01))
+ (process-send-string proc babel-body)
+ (process-send-eof proc)
+ (while (eq (process-status proc) 'run)
+ (sit-for 0.1))))
+
+ ;; run project
+ (let* ((err-buff (get-buffer-create rustic-babel-compilation-buffer-name))
+ (params '("cargo" "run" "--quiet"))
+ (inhibit-read-only t))
+ (rustic-make-process
+ :name rustic-babel-process-name
+ :buffer err-buff
+ :command params
+ :filter #'rustic-compilation-filter
+ :sentinel #'rustic-babel-run-sentinel)))
+
+ (let* ((project (car (reverse (split-string rustic-babel-dir "/"))))
+ (result (format "error: Could not compile `%s`." project)))
+ (rustic-babel-build-update-result-block result))
+ (rustic-with-spinner rustic-babel-spinner nil nil)
+ (if (= (length (with-current-buffer proc-buffer (buffer-string))) 0)
+ (kill-buffer proc-buffer)
+ (pop-to-buffer proc-buffer)))))
+
+(defun rustic-babel-run-sentinel (proc _output)
+ "Sentinel for babel project execution."
+ (let ((proc-buffer (process-buffer proc))
+ result)
+ (if (zerop (process-exit-status proc))
+ (progn
+ (with-current-buffer proc-buffer
+ (setq result (buffer-string)))
+ (rustic-babel-run-update-result-block result)
+ (rustic-with-spinner rustic-babel-spinner nil nil)
+ (unless rustic-babel-display-compilation-buffer
+ (kill-buffer proc-buffer)))
+ (progn
+ (with-current-buffer proc-buffer
+ (save-excursion
+ (save-match-data
+ (goto-char (point-min))
+ (when (re-search-forward "^thread '[^']+' panicked at '[^']+', ")
+ (goto-char (match-beginning 0))
+ (setq result (buffer-substring-no-properties (point) (line-end-position)))))))
+ (rustic-babel-run-update-result-block result)
+ (rustic-with-spinner rustic-babel-spinner nil nil)
+ (pop-to-buffer proc-buffer)))))
+
+(defun rustic-babel-build-update-result-block (result)
+ "Update result block with RESULT."
+ (let ((marker rustic-babel-src-location))
+ (with-current-buffer (marker-buffer marker)
+ (goto-char marker)
+ (org-babel-remove-result)
+ (org-babel-insert-result result))))
+
+(defun rustic-babel-run-update-result-block (result)
+ "Update result block with RESULT."
+ (let ((marker rustic-babel-src-location))
+ (with-current-buffer (marker-buffer marker)
+ (goto-char marker)
+
+ (let ((file (cdr (assq :file rustic-babel-params)))
+ (results-params (cdr (assq :result-params rustic-babel-params))))
+ ;; If non-empty result and :file then write to :file.
+ (when (and file results-params)
+ (when result
+ (with-temp-file file
+ (insert (org-babel-format-result
+ result (cdr (assq :sep rustic-babel-params))))))
+ (setq result file))
+
+ (org-babel-remove-result rustic-info)
+ (org-babel-insert-result result results-params rustic-info)))))
+
+(defun rustic-babel-format-sentinel (proc output)
+ "This sentinel is used by the process `rustic-babel-format', that runs
+after successful compilation."
+ (ignore-errors
+ (let ((proc-buffer (process-buffer proc))
+ (marker rustic-babel-src-location))
+ (save-excursion
+ (with-current-buffer proc-buffer
+ (when (string-match-p "^finished" output)
+ (with-current-buffer (marker-buffer marker)
+ (goto-char marker)
+ (org-babel-update-block-body
+ (with-current-buffer "rustic-babel-format-buffer"
+ (buffer-string)))))))
+ (kill-buffer "rustic-babel-format-buffer"))))
+
+(defun rustic-babel-generate-project (&optional expand)
+ "Create rust project in `org-babel-temporary-directory'.
+Return full path if EXPAND is t."
+ (let* ((default-directory org-babel-temporary-directory)
+ (dir (make-temp-file-internal "cargo" 0 "" nil)))
+ (shell-command-to-string (format "cargo new %s --bin --quiet" dir))
+ (if expand
+ (concat (expand-file-name dir) "/")
+ dir)))
+
+(defun rustic-babel-project ()
+ "In order to reduce the execution time when the project has
+dependencies, the project name is stored as a text property in the
+header of the org-babel block to check if the project already exists
+in `org-babel-temporary-directory'. If the project exists, reuse it.
+Otherwise create it with `rustic-babel-generate-project'."
+ (let* ((beg (org-babel-where-is-src-block-head))
+ (end (save-excursion (goto-char beg)
+ (line-end-position)))
+ (line (buffer-substring beg end)))
+ (let* ((project (symbol-name (get-text-property 0 'project line)))
+ (path (concat org-babel-temporary-directory "/" project "/")))
+ (if (file-directory-p path)
+ (progn
+ (put-text-property beg end 'project (make-symbol project))
+ project)
+ (let ((new (rustic-babel-generate-project)))
+ (put-text-property beg end 'project (make-symbol new))
+ new)))))
+
+(defun crate-dependencies (name version features)
+ "Generate a Cargo.toml [dependencies] entry for a crate given a version and features."
+ (let ((version-string (concat "version = \"" version "\""))
+ (features-string
+ (if features
+ (concat "features = [" (mapconcat (lambda (s) (concat "\"" s "\"")) features ", ") "]")
+ nil)))
+ (let ((toml-entry (string-join (remove nil (list version-string features-string)) ", ")))
+ (concat name " = {" toml-entry "}"))))
+
+(defun cargo-toml-dependencies (crate-versions crate-features)
+ "Generate the [dependencies] section of a Cargo.toml file given crates and their versions & features."
+ (let ((dependencies ""))
+ (dolist (crate-and-version crate-versions)
+ (let ((name (car crate-and-version))
+ (version (cdr crate-and-version)))
+ (let ((features (cdr (assoc name crate-features))))
+ (setq name (symbol-name name))
+ (when (numberp version)
+ (setq version (number-to-string version)))
+ (when (not (listp features))
+ (setq features (list features)))
+ (let ((cargo-toml-entry (crate-dependencies name version features)))
+ (setq dependencies (concat dependencies cargo-toml-entry "\n"))))))
+ (setq dependencies (concat "[dependencies]\n" dependencies))))
+
+(defun rustic-babel-cargo-toml (dir params)
+ "Append crates to Cargo.toml.
+Use org-babel parameter crates from PARAMS and add them to the project in
+directory DIR."
+ (let ((crates (cdr (assq :crates params)))
+ (features (cdr (assq :features params)))
+ (toml (expand-file-name "Cargo.toml" dir)))
+ (let ((dependencies (cargo-toml-dependencies crates features)))
+ (make-directory (file-name-directory toml) t)
+ (with-temp-file toml
+ (condition-case nil
+ (insert-file-contents toml)
+ (file-missing))
+ (let ((s (nth 0 (split-string (buffer-string) "\\[dependencies]"))))
+ (erase-buffer)
+ (insert s)
+ (insert dependencies))))))
+
+(defun org-babel-execute:rustic (body params)
+ "Execute a block of Rust code with org-babel.
+
+If called while there's a live Rust babel process, ask user whether to
+kill the running process."
+ (let ((p (get-process rustic-babel-process-name)))
+ (if (process-live-p p)
+ (progn
+ (rustic-process-kill-p p t)
+ nil)
+ (let* ((default-directory org-babel-temporary-directory)
+ (project (rustic-babel-project))
+ (dir (setq rustic-babel-dir (expand-file-name project)))
+ (main (expand-file-name "main.rs" (concat dir "/src"))))
+ (make-directory (file-name-directory main) t)
+ (rustic-babel-cargo-toml dir params)
+ (setq rustic-info (org-babel-get-src-block-info))
+ (setq rustic-babel-params params)
+
+ (rustic-with-spinner rustic-babel-spinner
+ (make-spinner rustic-spinner-type t 10)
+ '(rustic-babel-spinner (":Executing " (:eval (spinner-print rustic-babel-spinner))))
+ (spinner-start rustic-babel-spinner))
+
+ (let ((default-directory dir))
+ (write-region
+ (concat "#![allow(non_snake_case)]\n" body) nil main nil 0)
+ (rustic-babel-eval dir)
+ (setq rustic-babel-src-location
+ (set-marker (make-marker) (point) (current-buffer)))
+ project)))))
+
+(provide 'rustic-babel)
+;;; rustic-babel.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-cargo.el b/emacs.d/elpa/rustic-20210609.1900/rustic-cargo.el
new file mode 100644
index 0000000..3e56dd4
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-cargo.el
@@ -0,0 +1,530 @@
+;;; rustic-cargo.el --- Cargo based commands -*-lexical-binding: t-*-
+;;; Commentary:
+
+;; This library implements support for `cargo'.
+
+;;; Code:
+
+(require 'tabulated-list)
+
+(require 'rustic-compile)
+(require 'rustic-interaction) ; for rustic-beginning-of-function
+
+;;; Customization
+
+(defcustom rustic-cargo-bin "cargo"
+ "Path to cargo executable."
+ :type 'string
+ :group 'rustic-cargo)
+
+(defcustom rustic-cargo-open-new-project t
+ "If t then any project created with cargo-new will be opened automatically.
+If nil then the project is simply created."
+ :type 'boolean
+ :group 'rustic-cargo)
+
+(defvar rustic-cargo-outdated-face nil)
+(make-obsolete-variable 'rustic-cargo-outdated-face
+ "use the face `rustic-cargo-outdated' instead."
+ "1.2")
+
+(defface rustic-cargo-outdated
+ '((t (:foreground "red")))
+ "Face used for outdated crates."
+ :group 'rustic)
+
+(define-obsolete-face-alias 'rustic-cargo-outdated-upgrade-face
+ 'rustic-cargo-outdated-upgrade "1.2")
+
+(defface rustic-cargo-outdated-upgrade
+ '((t (:foreground "LightSeaGreen")))
+ "Face used for crates marked for upgrade."
+ :group 'rustic)
+
+;;; Clippy
+
+(defvar rustic-clippy-process-name "rustic-cargo-clippy-process"
+ "Process name for clippy processes.")
+
+(defvar rustic-clippy-buffer-name "*cargo-clippy*"
+ "Buffer name for clippy buffers.")
+
+(defvar rustic-clippy-arguments ""
+ "Holds arguments for 'cargo clippy', similar to `compilation-arguments`.")
+
+(define-derived-mode rustic-cargo-clippy-mode rustic-compilation-mode "cargo-clippy"
+ :group 'rustic)
+
+;;;###autoload
+(defun rustic-cargo-clippy-run (&optional args)
+ "Run `cargo clippy' with optional ARGS."
+ (interactive)
+ (let* ((command (list rustic-cargo-bin "clippy"))
+ (c (append command (split-string (if args args ""))))
+ (buf rustic-clippy-buffer-name)
+ (proc rustic-clippy-process-name)
+ (mode 'rustic-cargo-clippy-mode))
+ (rustic-compilation-process-live)
+ (rustic-compilation c (list :buffer buf :process proc :mode mode))))
+
+;;;###autoload
+(defun rustic-cargo-clippy (&optional arg)
+ "Run 'cargo clippy'.
+
+If ARG is not nil, use value as argument and store it in `rustic-clippy-arguments'.
+When calling this function from `rustic-popup-mode', always use the value of
+`rustic-clippy-arguments'."
+ (interactive "P")
+ (rustic-cargo-clippy-run
+ (cond (arg
+ (setq rustic-clippy-arguments (read-from-minibuffer "Cargo clippy arguments: " rustic-clippy-arguments)))
+ ((eq major-mode 'rustic-popup-mode)
+ rustic-clippy-arguments)
+ (t ""))))
+
+;;;###autoload
+(defun rustic-cargo-clippy-rerun ()
+ "Run 'cargo clippy' with `rustic-clippy-arguments'."
+ (interactive)
+ (rustic-cargo-clippy-run rustic-clippy-arguments))
+
+;;; Test
+
+(defvar rustic-test-process-name "rustic-cargo-test-process"
+ "Process name for test processes.")
+
+(defvar rustic-test-buffer-name "*cargo-test*"
+ "Buffer name for test buffers.")
+
+(defvar rustic-test-arguments ""
+ "Holds arguments for 'cargo test', similar to `compilation-arguments`.")
+
+(define-derived-mode rustic-cargo-test-mode rustic-compilation-mode "cargo-test"
+ :group 'rustic)
+
+;;;###autoload
+(defun rustic-cargo-test-run (&optional test-args)
+ "Start compilation process for 'cargo test' with optional TEST-ARGS."
+ (interactive)
+ (rustic-compilation-process-live)
+ (let* ((command (list rustic-cargo-bin "test"))
+ (c (append command (split-string (if test-args test-args ""))))
+ (buf rustic-test-buffer-name)
+ (proc rustic-test-process-name)
+ (mode 'rustic-cargo-test-mode))
+ (rustic-compilation c (list :buffer buf :process proc :mode mode))))
+
+;;;###autoload
+(defun rustic-cargo-test (&optional arg)
+ "Run 'cargo test'.
+
+If ARG is not nil, use value as argument and store it in `rustic-test-arguments'.
+When calling this function from `rustic-popup-mode', always use the value of
+`rustic-test-arguments'."
+ (interactive "P")
+ (rustic-cargo-test-run
+ (cond (arg
+ (setq rustic-test-arguments (read-from-minibuffer "Cargo test arguments: " rustic-test-arguments)))
+ ((eq major-mode 'rustic-popup-mode)
+ rustic-test-arguments)
+ (t ""))))
+
+;;;###autoload
+(defun rustic-cargo-test-rerun ()
+ "Run 'cargo test' with `rustic-test-arguments'."
+ (interactive)
+ (rustic-cargo-test-run rustic-test-arguments))
+
+;;;###autoload
+(defun rustic-cargo-current-test ()
+ "Run 'cargo test' for the test near point."
+ (interactive)
+ (rustic-compilation-process-live)
+ (-if-let (func-name (rustic-cargo--get-current-fn-fullname))
+ (let* ((command (list rustic-cargo-bin "test" func-name))
+ (c (append command (split-string rustic-test-arguments)))
+ (buf rustic-test-buffer-name)
+ (proc rustic-test-process-name)
+ (mode 'rustic-cargo-test-mode))
+ (rustic-compilation c (list :buffer buf :process proc :mode mode)))
+ (message "Could not find test at point.")))
+
+(defconst rustic-cargo-mod-regexp
+ "^\s*mod\s+\\([[:word:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*\\)\s*{")
+(defconst rustic-cargo-fn-regexp
+ "^\s*\\(?:async\s+\\)?\s*fn\s+\\([^(]+\\)\s*(")
+
+(defun rustic-cargo--get-current-fn-fullname()
+ "Return full name of the fn around point including module name if any."
+ (let ((mod (rustic-cargo--get-current-mod))
+ (fn (rustic-cargo--get-current-fn-name)))
+ (if mod
+ (concat mod "::" fn)
+ fn)))
+
+(defun rustic-cargo--get-current-mod ()
+ "Return mod name around point or nil."
+ (save-excursion
+ (when (search-backward-regexp rustic-cargo-mod-regexp nil t)
+ (match-string 1))))
+
+(defun rustic-cargo--get-current-line-fn-name()
+ "Return fn name from the current line or nil."
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (when (search-forward-regexp rustic-cargo-fn-regexp (line-end-position) t)
+ (match-string 1))))
+
+(defun rustic-cargo--get-current-fn-name()
+ "Return fn name around point or nil."
+ (save-excursion
+ (or (rustic-cargo--get-current-line-fn-name)
+ (progn
+ (rustic-beginning-of-function)
+ (rustic-cargo--get-current-line-fn-name)))))
+
+;;; Outdated
+
+(defvar rustic-cargo-outdated-process-name "rustic-cargo-outdated-process")
+
+(defvar rustic-cargo-oudated-buffer-name "*cargo-outdated*")
+
+(defvar rustic-cargo-outdated-spinner nil)
+
+(defvar rustic-cargo-outdated-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map tabulated-list-mode-map)
+ (define-key map (kbd "m") 'rustic-cargo-menu-mark-unmark)
+ (define-key map (kbd "u") 'rustic-cargo-mark-upgrade)
+ (define-key map (kbd "U") 'rustic-cargo-mark-all-upgrades)
+ (define-key map (kbd "x") 'rustic-cargo-upgrade-execute)
+ (define-key map (kbd "r") 'rustic-cargo-reload-outdated)
+ (define-key map (kbd "c") 'rustic-compile)
+ (define-key map (kbd "q") 'quit-window)
+ map)
+ "Local keymap for `rustic-cargo-outdated-mode' buffers.")
+
+(define-derived-mode rustic-cargo-outdated-mode tabulated-list-mode "cargo-outdated"
+ "Major mode for viewing outdated crates in the current workspace."
+ (setq truncate-lines t)
+ (setq tabulated-list-format
+ `[("Name" 25 nil)
+ ("Project" 10 nil)
+ ("Compat" 10 nil)
+ ("Latest" 10 nil)
+ ("Kind" 10 nil)
+ ("Platform" 0 nil)])
+ (setq tabulated-list-padding 2)
+ (tabulated-list-init-header))
+
+;;;###autoload
+(defun rustic-cargo-outdated (&optional path)
+ "Use 'cargo outdated' to list outdated packages in `tabulated-list-mode'.
+Execute process in PATH."
+ (interactive)
+ (let* ((dir (or path (rustic-buffer-workspace)))
+ (buf (get-buffer-create rustic-cargo-oudated-buffer-name))
+ (default-directory dir)
+ (inhibit-read-only t))
+ (make-process :name rustic-cargo-outdated-process-name
+ :buffer buf
+ :command '("cargo" "outdated" "--depth" "1")
+ :filter #'rustic-cargo-outdated-filter
+ :sentinel #'rustic-cargo-outdated-sentinel)
+ (with-current-buffer buf
+ (setq default-directory dir)
+ (erase-buffer)
+ (rustic-cargo-outdated-mode)
+ (rustic-with-spinner rustic-cargo-outdated-spinner
+ (make-spinner rustic-spinner-type t 10)
+ '(rustic-cargo-outdated-spinner
+ (":Executing " (:eval (spinner-print rustic-cargo-outdated-spinner))))
+ (spinner-start rustic-cargo-outdated-spinner)))
+ (display-buffer buf)))
+
+;;;###autoload
+(defun rustic-cargo-reload-outdated ()
+ "Update list of outdated packages."
+ (interactive)
+ (rustic-cargo-outdated default-directory))
+
+(defun rustic-cargo-outdated-filter (proc output)
+ "Filter for rustic-cargo-outdated-process."
+ (let ((inhibit-read-only t))
+ (with-current-buffer (process-buffer proc)
+ (insert output))))
+
+(defun rustic-cargo-outdated-sentinel (proc _output)
+ "Sentinel for rustic-cargo-outdated-process."
+ (let ((buf (process-buffer proc))
+ (inhibit-read-only t)
+ (exit-status (process-exit-status proc)))
+ (if (zerop exit-status)
+ (with-current-buffer buf
+ (goto-char (point-min))
+ (forward-line 2)
+ (let ((packages (split-string
+ (buffer-substring (point) (point-max)) "\n" t)))
+ (erase-buffer)
+ (rustic-cargo-outdated-generate-menu packages))
+ (pop-to-buffer buf))
+ (with-current-buffer buf
+ (let ((out (buffer-string)))
+ (if (= exit-status 101)
+ (rustic-cargo-install-crate-p "outdated")
+ (message out))))))
+ (rustic-with-spinner rustic-cargo-outdated-spinner nil nil))
+
+(defun rustic-cargo-install-crate-p (crate)
+ "Ask whether to install crate CRATE."
+ (let ((cmd (format "cargo install cargo-%s" crate)))
+ (when (yes-or-no-p (format "Cargo-%s missing. Install ? " crate))
+ (async-shell-command cmd "cargo" "cargo-error"))))
+
+(defun rustic-cargo-outdated-generate-menu (packages)
+ "Re-populate the `tabulated-list-entries' with PACKAGES."
+ (setq tabulated-list-entries
+ (mapcar #'rustic-cargo-outdated-menu-entry packages))
+ (tabulated-list-print t))
+
+(defun rustic-cargo-outdated-menu-entry (crate)
+ "Return a package entry of CRATE suitable for `tabulated-list-entries'."
+ (let* ((fields (split-string crate "\s\s+" ))
+ (name (nth 0 fields))
+ (project (nth 1 fields))
+ (compat (nth 2 fields)))
+ (list name `[,name
+ ,project
+ ,(if (when (not (string-match "^-" compat))
+ (version< project compat))
+ (propertize compat 'font-lock-face 'rustic-cargo-outdated)
+ compat)
+ ,(nth 3 fields)
+ ,(nth 4 fields)
+ ,(nth 5 fields)])))
+
+;;;###autoload
+(defun rustic-cargo-mark-upgrade ()
+ "Mark an upgradable package."
+ (interactive)
+ (let* ((crate (tabulated-list-get-entry (point)))
+ (v (read-from-minibuffer "Update to version: "
+ (substring-no-properties (elt crate 2))))
+ (inhibit-read-only t))
+ (when v
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (save-match-data
+ (when (search-forward (elt crate 0))
+ (replace-match (propertize (elt crate 0)
+ 'font-lock-face
+ 'rustic-cargo-outdated-upgrade)))
+ (goto-char (line-beginning-position))
+ (when (search-forward (elt crate 1))
+ (replace-match (propertize v
+ 'font-lock-face
+ 'rustic-cargo-outdated-upgrade)))))
+ (tabulated-list-put-tag "U" t))))
+
+;;;###autoload
+(defun rustic-cargo-mark-all-upgrades ()
+ "Mark all upgradable packages in the Package Menu."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let ((project (aref (tabulated-list-get-entry) 1))
+ (compat (aref (tabulated-list-get-entry) 2)))
+ (if (or (string-match "^-" compat)
+ (not (version< project compat)))
+ (forward-line)
+ (tabulated-list-put-tag "U" t))))))
+
+;;;###autoload
+(defun rustic-cargo-menu-mark-unmark ()
+ "Clear any marks on a package."
+ (interactive)
+ (tabulated-list-put-tag " " t))
+
+;;;###autoload
+(defun rustic-cargo-upgrade-execute ()
+ "Perform marked menu actions."
+ (interactive)
+ (let (crates)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let* ((cmd (char-after))
+ (crate (tabulated-list-get-entry (point))))
+ (when (eq cmd ?U)
+ (push crate crates)))
+ (forward-line)))
+ (if crates
+ (let ((msg (format "Upgrade %s ?" (mapconcat #'(lambda (x) (elt x 0)) crates " "))))
+ (when (yes-or-no-p msg)
+ (rustic-cargo-upgrade-crates crates)))
+ (user-error "No operations specified"))))
+
+(defun rustic-cargo-upgrade-crates (crates)
+ "Upgrade CRATES."
+ (let (upgrade)
+ (dolist (crate crates)
+ (setq upgrade (concat upgrade (format "%s@%s " (elt crate 0) (elt crate 2)))))
+ (let ((output (shell-command-to-string (format "cargo upgrade %s" upgrade))))
+ (if (string-match "error: no such subcommand:" output)
+ (rustic-cargo-install-crate-p "edit")
+ (rustic-cargo-reload-outdated)))))
+
+;;; New project
+
+(defun rustic-create-project (project-path is-new &optional bin)
+ "Run either 'cargo new' if IS-NEW is non-nil, or 'cargo init' otherwise.
+Creates or initializes the directory at the path specified by PROJECT-PATH. If
+BIN is not nil, create a binary application, otherwise a library."
+ (let* ((cmd (if is-new "new" "init"))
+ (bin (if (or bin (y-or-n-p "Create new binary package? "))
+ "--bin"
+ "--lib"))
+ (new-sentinel (lambda (_process signal)
+ (when (equal signal "finished\n")
+ (message (format "Created new package: %s"
+ (file-name-base project-path)))
+ (when rustic-cargo-open-new-project
+ (find-file (concat project-path
+ (if (string= bin "--bin")
+ "/src/main.rs"
+ "/src/lib.rs")))))))
+ (proc (format "rustic-cargo-%s-process" cmd))
+ (buf (format "*cargo-%s*" cmd)))
+ (make-process :name proc
+ :buffer buf
+ :command (list rustic-cargo-bin cmd bin project-path)
+ :sentinel new-sentinel)))
+
+;;;###autoload
+(defun rustic-cargo-new (project-path &optional bin)
+ "Run 'cargo new' to start a new package in the path specified by PROJECT-PATH.
+If BIN is not nil, create a binary application, otherwise a library."
+ (interactive "DProject path: ")
+ (rustic-create-project project-path t bin))
+
+;;;###autoload
+(defun rustic-cargo-init (project-path &optional bin)
+ "Run 'cargo init' to initialize a directory in the path specified by PROJECT-PATH.
+If BIN is not nil, create a binary application, otherwise a library."
+ (interactive "DProject path: ")
+ (rustic-create-project project-path nil bin))
+
+;;; Cargo commands
+
+(defun rustic-run-cargo-command (command &optional args)
+ "Run the specified COMMAND with cargo."
+ (rustic-compilation-process-live)
+ (rustic-compilation-start (split-string command) args))
+
+;;;###autoload
+(defun rustic-cargo-build ()
+ "Run 'cargo build' for the current project."
+ (interactive)
+ (rustic-run-cargo-command "cargo build"))
+
+;;;###autoload
+(defun rustic-cargo-run (&optional arg)
+ "Run 'cargo run' for the current project.
+If running with prefix command `C-u', read whole command from minibuffer."
+ (interactive "P")
+ (let* ((command (if arg
+ (read-from-minibuffer "Cargo run command: " "cargo run ")
+ (concat rustic-cargo-bin " run "
+ (read-from-minibuffer
+ "Run arguments: "
+ (car compile-history)
+ nil nil
+ 'compile-history)))))
+ (rustic-run-cargo-command command (list :mode 'rustic-cargo-run-mode))))
+
+(define-derived-mode rustic-cargo-run-mode rustic-compilation-mode "Cargo run"
+ "Mode for 'cargo run' that derives from `rustic-compilation-mode', but uses
+the keymap of `comint-mode' so user input is possible."
+ (buffer-disable-undo)
+ (setq buffer-read-only nil)
+ (use-local-map comint-mode-map))
+
+;;;###autoload
+(defun rustic-cargo-clean ()
+ "Run 'cargo clean' for the current project."
+ (interactive)
+ (rustic-run-cargo-command "cargo clean"))
+
+;;;###autoload
+(defun rustic-cargo-check ()
+ "Run 'cargo check' for the current project."
+ (interactive)
+ (rustic-run-cargo-command "cargo check"))
+
+;;;###autoload
+(defun rustic-cargo-bench ()
+ "Run 'cargo bench' for the current project."
+ (interactive)
+ (rustic-run-cargo-command "cargo bench"))
+
+;;;###autoload
+(defun rustic-cargo-build-doc ()
+ "Build the documentation for the current project."
+ (interactive)
+ (if (y-or-n-p "Create documentation for dependencies?")
+ (rustic-run-cargo-command "cargo doc")
+ (rustic-run-cargo-command "cargo doc --no-deps")))
+
+;; TODO: buffer with cargo output should be in rustic-compilation-mode
+;;;###autoload
+(defun rustic-cargo-doc ()
+ "Open the documentation for the current project in a browser.
+The documentation is built if necessary."
+ (interactive)
+ (if (y-or-n-p "Open docs for dependencies as well?")
+ ;; open docs only works with synchronous process
+ (shell-command "cargo doc --open")
+ (shell-command "cargo doc --open --no-deps")))
+
+;;; cargo edit
+
+(defun rustic-cargo-edit-installed-p ()
+ "Check if cargo-edit is installed. If not, ask the user if he wants to install it."
+ (if (executable-find "cargo-add") t (rustic-cargo-install-crate-p "edit") nil))
+
+;;;###autoload
+(defun rustic-cargo-add (&optional arg)
+ "Add crate to Cargo.toml using 'cargo add'.
+If running with prefix command `C-u', read whole command from minibuffer."
+ (interactive "P")
+ (when (rustic-cargo-edit-installed-p)
+ (let* ((command (if arg
+ (read-from-minibuffer "Cargo add command: " "cargo add ")
+ (concat "cargo add " (read-from-minibuffer "Crate: ")))))
+ (rustic-run-cargo-command command))))
+
+;;;###autoload
+(defun rustic-cargo-rm (&optional arg)
+ "Remove crate from Cargo.toml using 'cargo rm'.
+If running with prefix command `C-u', read whole command from minibuffer."
+ (interactive "P")
+ (when (rustic-cargo-edit-installed-p)
+ (let* ((command (if arg
+ (read-from-minibuffer "Cargo rm command: " "cargo rm ")
+ (concat "cargo rm " (read-from-minibuffer "Crate: ")))))
+ (rustic-run-cargo-command command))))
+
+;;;###autoload
+(defun rustic-cargo-upgrade (&optional arg)
+ "Upgrade dependencies as specified in the local manifest file using 'cargo upgrade'.
+If running with prefix command `C-u', read whole command from minibuffer."
+ (interactive "P")
+ (when (rustic-cargo-edit-installed-p)
+ (let* ((command (if arg
+ (read-from-minibuffer "Cargo upgrade command: " "cargo upgrade ")
+ (concat "cargo upgrade"))))
+ (rustic-run-cargo-command command))))
+
+(provide 'rustic-cargo)
+;;; rustic-cargo.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-compile.el b/emacs.d/elpa/rustic-20210609.1900/rustic-compile.el
new file mode 100644
index 0000000..0742a1f
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-compile.el
@@ -0,0 +1,540 @@
+;;; rustic-compile.el --- Compile facilities -*-lexical-binding: t-*-
+
+;;; Commentary:
+
+;; Unlike compile.el, rustic makes use of a non dumb terminal in order to receive
+;; all ANSI control sequences, which get translated by xterm-color.
+;; This file also adds a derived compilation mode. Error matching regexes from
+;; compile.el are removed.
+
+;;; Code:
+
+(require 'markdown-mode)
+(require 'xterm-color)
+
+(require 'compile)
+
+(require 'rustic)
+
+(defvar rustic-format-trigger)
+(defvar rustic-format-on-save)
+
+;;; Customization
+
+(defgroup rustic-compilation nil
+ "Rust Compilation."
+ :group 'rustic
+ :group 'processes)
+
+(defcustom rustic-compile-command (purecopy "cargo build")
+ "Default command for rust compilation."
+ :type 'string
+ :group 'rustic-compilation)
+
+(defcustom rustic-compile-display-method 'display-buffer
+ "Default function used for displaying compilation buffer."
+ :type 'function
+ :group 'rustic-compilation)
+
+(defcustom rustic-compile-backtrace "0"
+ "Set environment variable `RUST_BACKTRACE'."
+ :type '(choice (string :tag "0")
+ (string :tag "1")
+ (string :tag "full"))
+ :group 'rustic-compilation)
+
+(defcustom rustic-list-project-buffers-function
+ (if (fboundp 'projectile-project-buffers)
+ 'projectile-project-buffers
+ 'rustic-project-buffer-list)
+ "Function used to list buffers belonging to current project."
+ :type '(choice (const projectile-project-buffers)
+ (const rustic-project-buffer-list)
+ function)
+ :group 'rustic)
+
+;;; Faces
+
+(define-obsolete-face-alias 'rustic-message-face
+ 'rustic-message "1.2")
+(define-obsolete-face-alias 'rustic-compilation-error-face
+ 'rustic-compilation-error "1.2")
+(define-obsolete-face-alias 'rustic-compilation-warning-face
+ 'rustic-compilation-warning "1.2")
+(define-obsolete-face-alias 'rustic-compilation-info-face
+ 'rustic-compilation-info "1.2")
+(define-obsolete-face-alias 'rustic-compilation-line-face
+ 'rustic-compilation-line "1.2")
+(define-obsolete-face-alias 'rustic-compilation-column-face
+ 'rustic-compilation-column "1.2")
+
+(defface rustic-message
+ '((t :inherit default))
+ "Don't use `compilation-message-face', as ansi colors get messed up."
+ :group 'rustic-compilation)
+
+(defface rustic-compilation-error
+ '((t :inherit default))
+ "Override `compilation-error-face' for rust compilation."
+ :group 'rustic-compilation)
+
+(defface rustic-compilation-warning
+ '((t :inherit default))
+ "Override `compilation-warning-face' for rust compilation."
+ :group 'rustic-compilation)
+
+(defface rustic-compilation-info
+ '((t :inherit default))
+ "Override `compilation-info-face' for rust compilation."
+ :group 'rustic-compilation)
+
+(defface rustic-compilation-line
+ '((t :inherit default))
+ "Override `compilation-line-face' for rust compilation."
+ :group 'rustic-compilation)
+
+(defface rustic-compilation-column
+ '((t :inherit default))
+ "Override `compilation-column-face' for rust compilation."
+ :group 'rustic-compilation)
+
+(defcustom rustic-ansi-faces ["black"
+ "red3"
+ "green3"
+ "yellow3"
+ "blue2"
+ "magenta3"
+ "cyan3"
+ "white"]
+ "Term ansi faces."
+ :type '(vector string string string string string string string string)
+ :group 'rustic-compilation)
+
+;;; Compilation-mode
+
+(defvar rustic-compilation-mode-map
+ (let ((map (make-sparse-keymap)))
+ (suppress-keymap map t)
+ (set-keymap-parent map compilation-mode-map)
+ (define-key map "p" 'rustic-popup)
+ (define-key map "g" 'rustic-recompile)
+ map)
+ "Keymap for rust compilation log buffers.")
+
+(defvar rustic-compilation-error
+ (let ((err "^error[^:]*:[^\n]*\n\s*-->\s")
+ (file "\\([^\n]+\\)")
+ (start-line "\\([0-9]+\\)")
+ (start-col "\\([0-9]+\\)"))
+ (let ((re (concat err file ":" start-line ":" start-col)))
+ (cons re '(1 2 3))))
+ "Create hyperlink in compilation buffers for rust errors.")
+
+(defvar rustic-compilation-warning
+ (let ((warning "^warning:[^\n]*\n\s*-->\s")
+ (file "\\([^\n]+\\)")
+ (start-line "\\([0-9]+\\)")
+ (start-col "\\([0-9]+\\)"))
+ (let ((re (concat warning file ":" start-line ":" start-col)))
+ (cons re '(1 2 3 1)))) ;; 1 for warning
+ "Create hyperlink in compilation buffers for rust warnings.")
+
+(defvar rustic-compilation-info
+ (let ((file "\\([^\n]+\\)")
+ (start-line "\\([0-9]+\\)")
+ (start-col "\\([0-9]+\\)"))
+ (let ((re (concat "^ *::: " file ":" start-line ":" start-col)))
+ (cons re '(1 2 3 0)))) ;; 0 for info type
+ "Create hyperlink in compilation buffers for file paths preceded by ':::'.")
+
+(defvar rustic-compilation-panic
+ (let ((panic "thread '[^']+' panicked at '[^']+', ")
+ (file "\\([^\n]+\\)")
+ (start-line "\\([0-9]+\\)")
+ (start-col "\\([0-9]+\\)"))
+ (let ((re (concat panic file ":" start-line ":" start-col)))
+ (cons re '(1 2 3))))
+ "Match thread panics.")
+
+(define-compilation-mode rustic-compilation-mode "rust-compilation"
+ "Rust compilation mode.
+
+Error matching regexes from compile.el are removed."
+ (setq-local compilation-message-face 'rustic-message)
+ (setq-local compilation-error-face 'rustic-compilation-error)
+ (setq-local compilation-warning-face 'rustic-compilation-warning)
+ (setq-local compilation-info-face 'rustic-compilation-info)
+ (setq-local compilation-column-face 'rustic-compilation-column)
+ (setq-local compilation-line-face 'rustic-compilation-line)
+
+ (setq-local xterm-color-names-bright rustic-ansi-faces)
+ (setq-local xterm-color-names rustic-ansi-faces)
+
+ (setq-local compilation-error-regexp-alist-alist nil)
+ (add-to-list 'compilation-error-regexp-alist-alist
+ (cons 'rustic-error rustic-compilation-error))
+ (add-to-list 'compilation-error-regexp-alist-alist
+ (cons 'rustic-warning rustic-compilation-warning))
+ (add-to-list 'compilation-error-regexp-alist-alist
+ (cons 'rustic-info rustic-compilation-info))
+ (add-to-list 'compilation-error-regexp-alist-alist
+ (cons 'rustic-panic rustic-compilation-panic))
+
+ (setq-local compilation-error-regexp-alist nil)
+ (add-to-list 'compilation-error-regexp-alist 'rustic-error)
+ (add-to-list 'compilation-error-regexp-alist 'rustic-warning)
+ (add-to-list 'compilation-error-regexp-alist 'rustic-info)
+ (add-to-list 'compilation-error-regexp-alist 'rustic-panic)
+
+ (add-hook 'compilation-filter-hook #'rustic-insert-errno-button nil t))
+
+;;; Compilation Process
+
+(defvar rustic-compilation-process-name "rustic-compilation-process"
+ "Process name for rust compilation processes.")
+
+(defvar rustic-compilation-buffer-name "*rustic-compilation*"
+ "Buffer name for rust compilation process buffers.")
+
+(defun rustic-make-process (&rest args)
+ "Wrapper for `make-process'.
+
+Set environment variables for rust process."
+ (let ((coding-system-for-read 'binary)
+ (process-environment (nconc
+ (list
+ (format "TERM=%s" "ansi")
+ (format "RUST_BACKTRACE=%s" rustic-compile-backtrace))
+ process-environment)))
+ (let ((process (apply
+ #'start-file-process (plist-get args :name)
+ (plist-get args :buffer)
+ (plist-get args :command))))
+ (set-process-filter process (plist-get args :filter))
+ (set-process-sentinel process (plist-get args :sentinel))
+ (set-process-coding-system process 'utf-8-emacs-unix 'utf-8-emacs-unix)
+ process)))
+
+(defun rustic-compilation-setup-buffer (buf dir mode &optional no-mode-line)
+ "Prepare BUF for compilation process."
+ (let ((inhibit-read-only t))
+ (with-current-buffer buf
+ (erase-buffer)
+ (setq default-directory dir)
+ (funcall mode)
+ (unless no-mode-line
+ (setq mode-line-process
+ '((:propertize ":%s" face compilation-mode-line-run)
+ compilation-mode-line-errors)))
+ (force-mode-line-update)
+ (if (or compilation-auto-jump-to-first-error
+ (eq compilation-scroll-output 'first-error))
+ (set (make-local-variable 'compilation-auto-jump-to-next) t))
+ (sit-for 0))))
+
+(defvar rustic-before-compilation-hook nil)
+
+(defun rustic-compilation-start (command &optional args)
+ "Start a compilation process COMMAND with ARGS.
+ARGS is a plist that affects how the process is run,
+see `rustic-compilation' for details. First run
+`rustic-before-compilation-hook' and if any of these
+functions fails, then do not start compilation."
+ (when (run-hook-with-args-until-failure 'rustic-before-compilation-hook)
+ (rustic-compilation command args)))
+
+(defun rustic-compilation (command &optional args)
+ "Start a compilation process with COMMAND.
+
+ARGS is a plist that affects how the process is run.
+- `:no-display' don't display buffer when starting compilation process
+- `:buffer' name for process buffer
+- `:process' name for compilation process
+- `:mode' mode for process buffer
+- `:directory' set `default-directory'
+- `:sentinel' process sentinel"
+ (let ((buf (get-buffer-create
+ (or (plist-get args :buffer) rustic-compilation-buffer-name)))
+ (process (or (plist-get args :process) rustic-compilation-process-name))
+ (mode (or (plist-get args :mode) 'rustic-compilation-mode))
+ (directory (or (plist-get args :directory) (rustic-buffer-workspace)))
+ (sentinel (or (plist-get args :sentinel) #'compilation-sentinel)))
+ (rustic-compilation-setup-buffer buf directory mode)
+ (setq next-error-last-buffer buf)
+ (unless (plist-get args :no-display)
+ (funcall rustic-compile-display-method buf))
+ (with-current-buffer buf
+ (rustic-make-process :name process
+ :buffer buf
+ :command command
+ :filter #'rustic-compilation-filter
+ :sentinel sentinel))))
+
+(defun rustic-compilation-filter (proc string)
+ "Insert the text emitted by PROC.
+Translate STRING with `xterm-color-filter'."
+ (let ((buffer (process-buffer proc))
+ buffer-empty-p)
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (when (= (buffer-size) 0)
+ (setq buffer-empty-p t))
+ (let ((inhibit-read-only t)
+ ;; `save-excursion' doesn't use the right insertion-type for us.
+ (pos (copy-marker (point) t))
+ ;; `save-restriction' doesn't use the right insertion type either:
+ ;; If we are inserting at the end of the accessible part of the
+ ;; buffer, keep the inserted text visible.
+ (min (point-min-marker))
+ (max (copy-marker (point-max) t))
+ (compilation-filter-start (marker-position (process-mark proc)))
+ (xterm-string (xterm-color-filter string)))
+ (unwind-protect
+ (progn
+ (widen)
+ (goto-char compilation-filter-start)
+ ;; We used to use `insert-before-markers', so that windows with
+ ;; point at `process-mark' scroll along with the output, but we
+ ;; now use window-point-insertion-type instead.
+
+ (insert xterm-string)
+ (compilation--ensure-parse (point-max))
+
+ (unless comint-inhibit-carriage-motion
+ (comint-carriage-motion (process-mark proc) (point)))
+ (set-marker (process-mark proc) (point))
+ (run-hooks 'compilation-filter-hook))
+ (goto-char pos)
+ (narrow-to-region min max)
+ (set-marker pos nil)
+ (set-marker min nil)
+ (set-marker max nil))))
+ ;; Issue #101: set window point to `point-min' when `compilation-scroll-output' is nil
+ (when (and (not compilation-scroll-output) buffer-empty-p)
+ (let ((win (get-buffer-window buffer)))
+ (set-window-start win (point-min))
+ (set-window-point win (point-min)))))))
+
+(defun rustic-compilation-process-live (&optional nosave)
+ "Ask to kill live rustic process if any and call `rustic-save-some-buffers'.
+If optional NOSAVE is non-nil, then do not do the latter.
+Return non-nil if there was a live process."
+ (let ((procs (mapcan (lambda (proc)
+ (and proc
+ (let ((proc (get-process proc)))
+ (and (process-live-p proc)
+ (list proc)))))
+ (list rustic-compilation-process-name
+ (bound-and-true-p rustic-format-process-name)
+ (bound-and-true-p rustic-clippy-process-name)
+ (bound-and-true-p rustic-test-process-name)))))
+ (when (> (length procs) 1)
+ (error "BUG: Multiple live rustic processes: %s" procs))
+ (when procs
+ (rustic-process-kill-p (car procs)))
+ (unless nosave
+ (rustic-save-some-buffers))
+ procs))
+
+(defun rustic-process-kill-p (proc &optional no-error)
+ "Don't allow two rust processes at once.
+
+If NO-ERROR is t, don't throw error if user chooses not to kill running process."
+ (if (yes-or-no-p
+ (format "`%s' is running; kill it? " proc))
+ (condition-case ()
+ (progn
+ (interrupt-process proc)
+ (sit-for 0.5)
+ (delete-process proc))
+ (error nil))
+ (unless no-error
+ (error "Cannot have two rust processes at once"))))
+
+(defun rustic-save-some-buffers ()
+ "Unlike `save-some-buffers', only consider project related files.
+
+The variable `buffer-save-without-query' can be used for customization and
+buffers are formatted after saving if turned on by `rustic-format-trigger'."
+ (let ((buffers (cl-remove-if-not
+ #'buffer-file-name
+ (if (fboundp rustic-list-project-buffers-function)
+ (funcall rustic-list-project-buffers-function)
+ (buffer-list))))
+ (b (get-buffer (bound-and-true-p rustic-format-buffer-name))))
+ (when (buffer-live-p b)
+ (kill-buffer b))
+ (dolist (buffer buffers)
+ (when (and (buffer-live-p buffer)
+ (buffer-modified-p buffer))
+ (with-current-buffer buffer
+ (let ((saved-p nil))
+ ;; also set rustic-format-on-save for backwards compatibility
+ (let ((rustic-format-trigger nil)
+ (rustic-format-on-save nil))
+ (setq saved-p
+ (if buffer-save-without-query
+ (progn (save-buffer) t)
+ (if (yes-or-no-p (format "Save file %s ? "
+ (buffer-file-name buffer)))
+ (progn (save-buffer) t)
+ nil))))
+ (when (and saved-p
+ (eq major-mode 'rustic-mode)
+ (fboundp 'rustic-maybe-format-after-save))
+ (rustic-maybe-format-after-save buffer))))))))
+
+(defun rustic-compile-goto-error-hook (orig-fun &rest args)
+ "Provide possibility use `compile-goto-error' on line numbers in compilation buffers.
+This hook checks if there's a line number at the beginning of the
+current line in an error section."
+ (-if-let* ((rustic-p (eq major-mode 'rustic-compilation-mode))
+ (line-contents (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))
+ (line-number-p (string-match "^[0-9]+\s+\|" line-contents))
+ (line-number (car (split-string line-contents))))
+ (save-excursion
+ ;; find compilation message in error
+ (while (not (or (get-text-property (point) 'compilation-message)
+ (bobp)))
+ (forward-line -1))
+ ;; get file of text property
+ (let* ((msg (get-text-property (point) 'compilation-message))
+ (loc (compilation--message->loc msg))
+ (file (caar (compilation--loc->file-struct loc))))
+ ;; open file of error and goto line number that we parsed from the line we are on
+ (with-current-buffer (find-file-other-window file)
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line (1- (string-to-number line-number)))))))
+ (apply orig-fun args)))
+
+(advice-add 'compile-goto-error :around #'rustic-compile-goto-error-hook)
+
+(defun rustic-compile-send-input ()
+ "Read string from minibuffer and send it to the rust process of the current
+buffer."
+ (interactive)
+ (let ((input (read-from-minibuffer "Send input to rust process: "))
+ (proc (get-buffer-process (current-buffer)))
+ (inhibit-read-only t))
+ (process-send-string proc (concat input "\n"))))
+
+
+;;; Rustc
+
+(defface rustic-errno-face
+ '((t :foreground "red3"))
+ "Error number face"
+ :group 'rustic-compilation)
+
+(defun rustic-insert-errno-button ()
+ "Insert buttons in `rustic-compilation-mode'."
+ (save-excursion
+ (let ((start compilation-filter-start)
+ (end (point)))
+ (goto-char start)
+ (save-match-data
+ (while (re-search-forward (concat "error\\[E[0-9]+\\]") end t)
+ (make-button (match-beginning 0)
+ (match-end 0)
+ :type 'rustc-errno))))))
+
+(defun rustic-explain-error (button)
+ "Open buffer with explanation for error at point."
+ (let* ((button-string (button-label button))
+ (errno (progn (string-match "E[0-9]+" button-string)
+ (match-string 0 button-string)))
+ (buf (get-buffer-create "*rust errno*"))
+ (inhibit-read-only t))
+ (with-current-buffer buf
+ (erase-buffer)
+ (insert (shell-command-to-string
+ (concat "rustc --explain=" errno)))
+ (markdown-view-mode)
+ (setq
+ header-line-format
+ (concat (propertize " " 'display
+ `(space :align-to (- right-fringe ,(1+ (length errno)))))
+ (propertize errno 'face 'rustic-errno-face)))
+ (setq-local markdown-fontify-code-blocks-natively t)
+ (setq-local markdown-fontify-code-block-default-mode 'rustic-mode)
+ (markdown-toggle-markup-hiding 1)
+ (goto-char (point-min)))
+ (pop-to-buffer buf)))
+
+(define-button-type 'rustc-errno
+ 'action #'rustic-explain-error
+ 'follow-link t
+ 'face 'rustic-errno-face
+ 'help-echo "mouse-1, RET: Explain errno")
+
+;;; Interactive
+
+;;;###autoload
+(defun rustic-compile (&optional arg)
+ "Compile rust project.
+
+If `compilation-read-command' is non-nil or if called with prefix
+argument ARG then read the command in the minibuffer. Otherwise
+use `rustic-compile-command'.
+
+In either store the used command in `compilation-arguments'."
+ (interactive "P")
+ (setq compilation-arguments
+ (if (or compilation-read-command arg)
+ (read-from-minibuffer "Compile command: "
+ (or compilation-arguments
+ rustic-compile-command))
+ rustic-compile-command))
+ (setq compilation-directory (rustic-buffer-workspace))
+ (rustic-compilation-process-live)
+ (rustic-compilation-start (split-string compilation-arguments)
+ (list :directory compilation-directory)))
+
+;;;###autoload
+(defun rustic-recompile ()
+ "Re-compile the program using `compilation-arguments'."
+ (interactive)
+ (let* ((command (or compilation-arguments rustic-compile-command))
+ (dir compilation-directory))
+ (rustic-compilation-process-live)
+ (rustic-compilation (split-string command) (list :directory dir))))
+
+;;; Spinner
+
+(require 'spinner)
+
+(defcustom rustic-display-spinner t
+ "Display spinner."
+ :type 'boolean
+ :group 'rustic)
+
+(defcustom rustic-spinner-type 'horizontal-moving
+ "Holds the type of spinner to be used in the mode-line.
+Takes a value accepted by `spinner-start'."
+ :type `(choice (choice :tag "Choose a spinner by name"
+ ,@(mapcar (lambda (c) (list 'const (car c)))
+ spinner-types))
+ (const :tag "A random spinner" random)
+ (repeat :tag "A list of symbols from `spinner-types' to randomly choose from"
+ (choice :tag "Choose a spinner by name"
+ ,@(mapcar (lambda (c) (list 'const (car c)))
+ spinner-types)))
+ (vector :tag "A user defined vector"
+ (repeat :inline t string))))
+
+(defmacro rustic-with-spinner (spinner val mode-line &rest body)
+ (declare (indent defun))
+ `(when rustic-display-spinner
+ (when (spinner-p ,spinner)
+ (spinner-stop ,spinner))
+ (setq ,spinner ,val)
+ (setq mode-line-process ,mode-line)
+ ,@body))
+
+;;; _
+(provide 'rustic-compile)
+;;; rustic-compile.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-doc.el b/emacs.d/elpa/rustic-20210609.1900/rustic-doc.el
new file mode 100644
index 0000000..b3743bd
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-doc.el
@@ -0,0 +1,385 @@
+;;; rustic-doc.el --- Browse rust documentation as .org files -*- lexical-binding: t -*-
+
+;; Copyright (c) 2020 Sam Hedin
+
+;; Author: Sam Hedin <sam.hedin@gmail.com>
+;; Jonas Møller <jonas.moeller2@protonmail.com>
+
+;;; Commentary:
+
+;; This package lets you convert rustic-doc html-files to org mode
+;; files, and lets you browse them with `rustic-doc-search'.
+
+;; Run `M-x rustic-doc-setup' to download the required files and
+;; convert the rust standard library.
+
+;; Run `M-x rustic-doc-convert-current-package' to generate and
+;; convert docs for the package you are currently visiting.
+
+;;; Code:
+
+(require 'url)
+(require 'lsp-mode)
+(require 'f)
+
+(eval-and-compile
+ (if (< emacs-major-version 27)
+ (defun rustic-doc--xdg-data-home ()
+ (or (getenv "XDG_DATA_HOME")
+ (concat (file-name-as-directory (getenv "HOME"))
+ ".local/share")))
+ (require 'xdg)
+ (fset 'rustic-doc--xdg-data-home 'xdg-data-home)))
+
+(defvar rustic-doc-lua-filter (concat (file-name-as-directory (getenv "HOME"))
+ ".local/bin/rustic-doc-filter.lua")
+ "Save location for the rustic-doc lua filter.")
+
+(defvar rustic-doc-convert-prog (concat (file-name-as-directory (getenv "HOME"))
+ ".local/bin/rustic-doc-convert.sh")
+ "Save location for the rustic-doc conversion script.")
+
+(defvar rustic-doc-source-repo
+ "https://raw.githubusercontent.com/brotzeit/rustic/master/rustic-doc/")
+
+(defvar rustic-doc-current-project nil
+ "Location to search for documentation.
+All projects and std by default, otherwise last open project and std.")
+
+(defvar rustic-doc-save-loc (concat (rustic-doc--xdg-data-home)
+ "/emacs/rustic-doc"))
+
+(defvar rustic-doc-resources
+ `((,rustic-doc-convert-prog
+ (:exec)
+ ,(concat rustic-doc-source-repo "convert.sh"))
+ (,rustic-doc-lua-filter
+ ()
+ ,(concat rustic-doc-source-repo "filter.lua"))))
+
+(defun rustic-doc-default-rg-search-command ()
+ "The default search command when using helm-ag.
+Needs to be a function because of its reliance on
+`rustic-doc-current-project'"
+ (concat "rg --smart-case --no-heading --color=never --line-number "
+ (if rustic-doc-current-project " -L" "")))
+
+(defcustom rustic-doc-rg-search-command 'rustic-doc-default-rg-search-command
+ "The default command string to pass helm-ag when searching."
+ :type 'function
+ :group 'rustic-doc)
+
+(defvar helm-ag-base-command)
+(defvar helm-ag-success-exit-status)
+(declare-function helm-ag "ext:helm-ag")
+
+(defun rustic-doc-default-search-function (search-dir search-term)
+ "Default search functionality.
+Uses helm-ag and ripgrep if possible, grep otherwise.
+Search for SEARCH-TERM inside SEARCH-DIR"
+ (cond
+ ((and (require 'helm-ag nil t) (executable-find "rg"))
+ (let* ((helm-ag-base-command (funcall rustic-doc-rg-search-command))
+ (helm-ag-success-exit-status '(0 2)))
+ (condition-case nil
+ (helm-ag search-dir search-term)
+ ;; If the search didn't turn anything up we re-run the search
+ ;; in the top level searchdir.
+ (error (helm-ag rustic-doc-save-loc search-term)))))
+ ((executable-find "rg")
+ (grep (format "%s '%s' %s"
+ (rustic-doc-default-rg-search-command)
+ search-term
+ search-dir)))
+ (t
+ (grep (format "grep -RPIni '%s' %s" search-term search-dir)))))
+
+
+(defcustom rustic-doc-search-function 'rustic-doc-default-search-function
+ "Function to use for searching documentation.
+The function should take search-dir and search-term as arguments."
+ :type 'function
+ :group 'rustic-doc)
+
+(defun rustic-doc--install-resources ()
+ "Install or update the rustic-doc resources."
+ (dolist (resource rustic-doc-resources)
+ (pcase resource
+ (`(,dst ,opts ,src)
+ (condition-case nil
+ (progn
+ (unless (f-exists? (f-dirname dst))
+ (f-mkdir (f-dirname dst)))
+ (url-copy-file src dst t)
+ (when (memq :exec opts)
+ (call-process (executable-find "chmod")
+ nil
+ nil
+ nil
+ "+x"
+ dst)))
+ (error (progn
+ (if (file-exists-p dst)
+ (message (format "Could not update %s, using existing one"
+ dst))
+ (error (format "Could not retrieve %s" dst)))))))
+ (x (error "Invalid resource spec: %s" x)))))
+
+;;;###autoload
+(defun rustic-doc-dumb-search (search-term)
+ "Search all projects and std for SEARCH-TERM.
+Use this when `rustic-doc-search' does not find what you're looking for.
+Add `universal-argument' to only search level 1 headers.
+See `rustic-doc-search' for more information."
+ (interactive (let ((short-name (alist-get 'short-name
+ (rustic-doc--thing-at-point))))
+ (list (read-string (format "search term, default %s: " short-name)
+ nil
+ nil
+ short-name))))
+ (rustic-doc-search search-term t))
+
+
+;;;###autoload
+(defun rustic-doc-search (search-term &optional root)
+ "Search the rust documentation for SEARCH-TERM.
+Only searches in headers (structs, functions, traits, enums, etc)
+to limit the number of results.
+To limit search results to only level 1 headers, add `universal-argument'
+Level 1 headers are things like struct or enum names.
+if ROOT is non-nil the search is performed from the root dir.
+This function tries to be smart and limits the search results
+as much as possible. If it ends up being so smart that
+it doesn't manage to find what you're looking for, try `rustic-doc-dumb-search'."
+ (interactive (let ((short-name (alist-get 'short-name
+ (rustic-doc--thing-at-point))))
+ (list (read-string (format "search term, default %s: " short-name)
+ nil
+ nil
+ short-name))))
+
+ (rustic-doc--update-current-project)
+ (let* ((thing-at-point (rustic-doc--thing-at-point))
+ (short-name (alist-get 'short-name thing-at-point))
+ ;; If the user did not accept the default search suggestion,
+ ;; we should not search in that suggestion's directory.
+ (search-dir
+ (cond
+ (root rustic-doc-save-loc)
+ ((string-equal short-name search-term)
+ (alist-get 'search-dir thing-at-point))
+ (t (rustic-doc--project-doc-dest))))
+ ;; If the prefix arg is provided, we only search for level 1
+ ;; headers by making sure that there is only one * at the
+ ;; beginning of the line.
+ (regex (if current-prefix-arg
+ (progn
+ (setq current-prefix-arg nil)
+ "^\\*")
+ "^\\*+"))
+ ;; This seq-reduce turns `enum option' into (kind of)
+ ;; `enum.*option', which lets there be chars between the
+ ;; searched words
+ (regexed-search-term
+ (concat regex
+ ;; Regex explanation
+ ;; `-' => Do not match if a return type. A search
+ ;; for Option should not show is_some -> Option
+ ;; `(' => Do not match if it's an argument name.
+ ;; `<' => Do not match if it's a generic type arg
+ (seq-reduce (lambda (acc s)
+ (concat acc "[^-\*(<]*" s))
+ (split-string search-term " ")
+ ""))))
+ (unless (file-directory-p rustic-doc-save-loc)
+ (rustic-doc-setup)
+ (message "Running first time setup. Please re-run your search\
+ once conversion has completed.")
+ (sleep-for 3))
+ ;; If the user has not run `rustic-doc-convert-current-package' in
+ ;; the current project, we create a default directory that only
+ ;; contains a symlink to std.
+ (unless (file-directory-p (rustic-doc--project-doc-dest))
+ (rustic-doc-create-project-dir))
+ (funcall rustic-doc-search-function search-dir regexed-search-term)))
+
+(defun rustic-doc--update-current-project ()
+ "Update `rustic-doc-current-project' if editing a rust file, otherwise leave it."
+ (when (and lsp-mode
+ (derived-mode-p 'rust-mode 'rustic-mode))
+ (setq rustic-doc-current-project (lsp-workspace-root))))
+
+(defun rustic-doc--deepest-dir (path)
+ "Find the deepest existing and non-empty arg-directory parent of PATH.
+We can sometimes infer the filepath from the crate name.
+E.g the enum std::option::Option is in the folder std/option.
+Some filepaths can not be inferred properly, seemingly because of
+URL `https://github.com/rust-lang/rust/issues/21934'.
+In these cases, the deepest dir will be the current project dir."
+ (if (and (file-exists-p path)
+ (file-directory-p path)
+ (not (f-empty-p path)))
+ path
+ (rustic-doc--deepest-dir (f-slash (f-dirname path)))))
+
+(defun rustic-doc--project-doc-dest ()
+ "The location of the documentation for the current or last seen project.
+If the user has not visited a project, returns the main doc directory."
+ (if rustic-doc-current-project
+ (f-join rustic-doc-save-loc
+ (f-filename rustic-doc-current-project))
+ rustic-doc-save-loc))
+
+(defun rustic-doc-create-project-dir ()
+ "Create a rustic-doc arg-directory for the current project. Link with std."
+ (let* ((link-tgt (concat (file-name-as-directory (rustic-doc--xdg-data-home))
+ "emacs/rustic-doc/std"))
+ (link-name (concat (rustic-doc--project-doc-dest)
+ "/std"))
+ (current-doc-dest (rustic-doc--project-doc-dest)))
+ (if current-doc-dest
+ (progn
+ (make-directory (rustic-doc--project-doc-dest)
+ t)
+ (make-symbolic-link link-tgt link-name t))
+ (message "Couldn't create project doc directory."))))
+
+;;;###autoload
+(defun rustic-doc-convert-current-package ()
+ "Convert the documentation for a project and its dependencies."
+ (interactive)
+ (unless (file-directory-p rustic-doc-save-loc)
+ (rustic-doc-setup)
+ (message "Running first time setup.")
+ (sleep-for 3))
+ (if rustic-doc-current-project
+ (progn
+ (message "Converting documentation for %s "
+ rustic-doc-current-project)
+ (if (/= 0 (call-process "cargo" nil "*cargo-makedocs*" nil "makedocs"))
+ (message "\
+cargo makedocs could not generate docs for the current package. \
+See buffer *cargo-makedocs* for more info")
+ (let* ((docs-src
+ (concat (file-name-as-directory rustic-doc-current-project)
+ "target/doc"))
+ ;; FIXME: Many projects could share the same docs.
+ ;; *However* that would have to be versioned, so
+ ;; we'll have to figure out a way to coerce `<crate>-<version>`
+ ;; strings out of cargo, or just parse the Cargo.toml file, but
+ ;; then we'd have to review different parsing solutions.
+ (finish-func (lambda (_p)
+ (message "Finished converting docs for %s"
+ rustic-doc-current-project))))
+ (rustic-doc-create-project-dir)
+ (rustic-doc--start-process "rustic-doc-convert"
+ rustic-doc-convert-prog
+ finish-func
+ docs-src
+ (rustic-doc--project-doc-dest)))))
+ (message "Could not find project to convert. Visit a rust project first! \
+\(Or activate rustic-doc-mode if you are in one)")))
+
+(defun rustic-doc-install-deps ()
+ "Install dependencies with Cargo."
+ (if (not (executable-find "cargo"))
+ (message "You need to have cargo installed to use rustic-doc")
+ (let ((missing-rg (not (executable-find "rg")))
+ (missing-fd (not (executable-find "fd")))
+ (missing-makedocs (not (executable-find "cargo-makedocs"))))
+ (when (and (or missing-fd missing-makedocs missing-rg)
+ (y-or-n-p "Missing some dependencies for rustic doc, install them? "))
+ (when missing-fd
+ (rustic-doc--start-process "install-fd" "cargo" nil "install" "fd-find"))
+ (when missing-rg
+ (rustic-doc--start-process "install-rg" "cargo" nil "install" "ripgrep"))
+ (when missing-makedocs
+ (rustic-doc--start-process "install-makedocs" "cargo" nil
+ "install" "cargo-makedocs"))))))
+
+;;;###autoload
+(defun rustic-doc-setup ()
+ "Setup or update rustic-doc filter and convert script. Convert std."
+ (interactive)
+ (rustic-doc--install-resources)
+ (rustic-doc-install-deps)
+ (message "Setup is converting the standard library")
+ (delete-directory (concat rustic-doc-save-loc "/std")
+ t)
+ (rustic-doc--start-process "rustic-doc-std-conversion"
+ rustic-doc-convert-prog
+ (lambda (_p)
+ (message "Finished converting docs for std"))
+ "std"))
+
+(defun rustic-doc--start-process (name program finish-func &rest program-args)
+ (let* ((buf (generate-new-buffer (concat "*" name "*")))
+ (proc (let ((process-connection-type nil))
+ (apply #'start-process name buf program program-args))))
+ (set-process-sentinel
+ proc (lambda (proc event)
+ (let ((buf (process-buffer proc)))
+ (if (string-match-p (regexp-quote "abnormally") event)
+ (message "Could not finish process: %s. \
+See the *Messages* buffer or %s for more info." event (concat "*" name "*"))
+ (when finish-func
+ (funcall finish-func proc))
+ (when (buffer-live-p buf)
+ (kill-buffer buf))))))
+ proc))
+
+(defun rustic-doc--thing-at-point ()
+ "Return info about `thing-at-point'. If `thing-at-point' is nil, return defaults."
+ (if-let ((active lsp-mode)
+ (lsp-content (-some->> (lsp--text-document-position-params)
+ (lsp--make-request "textDocument/hover")
+ (lsp--send-request)
+ (lsp:hover-contents)))
+ ;; `short-name' is the unqalified of a struct, function
+ ;; etc, like `Option'
+ (short-name (thing-at-point 'symbol t))
+ ;; If symbol at point is a primitive, the `value' key is
+ ;; different than in most cases. If it is a primitive, we
+ ;; concat the name with primitive for searching.
+ (lsp-info (or (nth 1
+ (split-string (gethash "value" lsp-content)))
+ (setq short-name
+ (concat "primitive "
+ (gethash "value" lsp-content)))))
+ ;; If short-name was `Option', long-name would be `std::option::Option'
+ (long-name (concat (cond
+ ((string-prefix-p "core" lsp-info)
+ (concat "std"
+ (seq-drop lsp-info 4)))
+ ((string-prefix-p "alloc" lsp-info)
+ (concat "std"
+ (seq-drop lsp-info 5)))
+ (t lsp-info))
+ "::"
+ short-name))
+ (search-dir (rustic-doc--deepest-dir
+ (concat (rustic-doc--project-doc-dest)
+ "/"
+ (seq-reduce (lambda (path p)
+ (concat path "/" p))
+ (split-string long-name "::")
+ "")))))
+ `((search-dir . ,search-dir)
+ (short-name . ,short-name))
+ `((search-dir . ,(rustic-doc--project-doc-dest))
+ (short-name . ,nil))))
+
+;;;###autoload
+(define-minor-mode rustic-doc-mode
+ "Convert rust html docs to .org, and browse the converted docs."
+ :lighter " browse rust documentation"
+ :keymap (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-#") 'rustic-doc-search)
+ map)
+ (dolist (mode '(rust-mode-hook rustic-mode-hook org-mode-hook))
+ (add-hook mode 'rustic-doc-mode))
+ (rustic-doc--update-current-project))
+
+(provide 'rustic-doc)
+
+;;; rustic-doc.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-flycheck.el b/emacs.d/elpa/rustic-20210609.1900/rustic-flycheck.el
new file mode 100644
index 0000000..ffc5ffc
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-flycheck.el
@@ -0,0 +1,201 @@
+;;; rustic-flycheck.el --- Flycheck support -*-lexical-binding: t-*-
+
+;;; Code:
+
+(eval-when-compile (require 'let-alist))
+
+(require 'flycheck)
+(require 'json)
+
+(require 'rustic)
+
+(defcustom rustic-flycheck-clippy-params "--message-format=json -Zunstable-options"
+ "Parameters for the flycheck clippy checker `rustic-clippy'."
+ :type 'string
+ :group 'rustic-flycheck)
+
+(defun rustic-flycheck-dirs-list (start end)
+ "Return a list of directories from START (inclusive) to END (exclusive).
+E.g., if START is '/a/b/c/d' and END is '/a', return the list
+'(/a/b/c/d /a/b/c /a/b) in this order.
+START and END are strings representing file paths. END should be
+above START in the file hierarchy; if not, the list stops at the
+root of the file hierarchy."
+ (let ((dirlist)
+ (dir (expand-file-name start))
+ (end (expand-file-name end)))
+ (while (not (or (equal dir (car dirlist)) ; avoid infinite loop
+ (file-equal-p dir end)))
+ (push dir dirlist)
+ (setq dir (directory-file-name (file-name-directory dir))))
+ (nreverse dirlist)))
+
+(defun rustic-flycheck-get-cargo-targets (manifest)
+ "Return the list of available Cargo targets for the given project.
+MANIFEST is the path to the Cargo.toml file of the project.
+Calls `cargo metadata --no-deps --manifest-path MANIFEST
+--format-version 1', parses and collects the targets for the
+current workspace, and returns them in a list, or nil if no
+targets could be found."
+ (let ((process-output-as-json
+ (lambda (program &rest args)
+ (with-temp-buffer
+ (let ((code-or-signal (apply 'process-file program nil '(t nil) nil args)))
+ (unless (equal code-or-signal 0)
+ ;; Prevent from displaying "JSON readtable error".
+ (let* ((args (combine-and-quote-strings (cons program args)))
+ (error-message (if (stringp code-or-signal)
+ (format "%s terminated by %s." args code-or-signal)
+ (format "%s exited with %s." args code-or-signal))))
+ (user-error error-message)))
+ (goto-char (point-min))
+ (let ((json-array-type 'list)
+ (json-object-type 'alist))
+ (json-read))))))
+ (cargo (funcall flycheck-executable-find "cargo")))
+ (unless cargo
+ (user-error "flycheck-rust cannot find `cargo'. Please \
+make sure that cargo is installed and on your PATH. See \
+http://www.flycheck.org/en/latest/user/troubleshooting.html for \
+more information on setting your PATH with Emacs."))
+ ;; metadata contains a list of packages, and each package has a list of
+ ;; targets. We concatenate all targets, regardless of the package.
+ (-when-let (packages (let-alist
+ (funcall process-output-as-json
+ cargo "metadata"
+ "--no-deps"
+ "--manifest-path" manifest
+ "--format-version" "1")
+ .packages))
+ (seq-map (lambda (pkg)
+ (let-alist pkg .targets))
+ packages))))
+
+(defun rustic-flycheck-find-cargo-target (file-name)
+ "Return the Cargo build target associated with FILE-NAME.
+
+FILE-NAME is the path of the file that is matched against the
+`src_path' value in the list of `targets' returned by `cargo
+read-manifest'.
+
+Return an alist ((KIND . k) (NAME . n) (REQUIRED-FEATURES . rf))
+where KIND is the target kind (lib, bin, test, example or bench),
+NAME the target name (usually, the crate name), and REQUIRED-FEATURES is the
+optional list of features required to build the selected target. If FILE-NAME
+exactly matches a target `src-path', this target is returned. Otherwise, return
+the closest matching target, or nil if no targets could be found.
+
+See http://doc.crates.io/manifest.html#the-project-layout for a
+description of the conventional Cargo project layout."
+ (-when-let* ((workspace (rustic-buffer-workspace t))
+ (manifest (file-local-name (concat workspace "Cargo.toml")))
+ (packages (rustic-flycheck-get-cargo-targets manifest))
+ (targets (-flatten-n 1 packages)))
+ (let ((target
+ (or
+ ;; If there is a target that matches the file-name exactly, pick
+ ;; that one
+ (seq-find (lambda (target)
+ (let-alist target (string= file-name .src_path)))
+ targets)
+ ;; Otherwise find the closest matching target by walking up the tree
+ ;; from FILE-NAME and looking for targets in each directory. E.g.,
+ ;; the file 'tests/common/a.rs' will look for a target in
+ ;; 'tests/common', then in 'tests/', etc.
+ (car (seq-find
+ (lambda (pair)
+ (-let [((&alist 'src_path target-path) . dir) pair]
+ (file-equal-p dir (file-name-directory target-path))))
+ ;; build a list of (target . dir) candidates
+ (-table-flat
+ 'cons targets
+ (rustic-flycheck-dirs-list file-name workspace))))
+ ;; If all else fails, just pick the first target
+ (car targets))))
+ ;; If target is 'custom-build', we pick another target from the same package (see GH-62)
+ (when (string= "custom-build" (let-alist target (car .kind)))
+ (setq target (->> packages
+ ;; find the same package as current build-script buffer
+ (--find (--any? (equal target it) it))
+ (--find (not (equal target it))))))
+ (when target
+ (let-alist target
+ (seq-filter (lambda (kv) (cdr kv))
+ (list (cons 'kind (rustic-flycheck-normalize-target-kind .kind))
+ (cons 'name .name)
+ (cons 'required-features .required-features))))))))
+
+(defun rustic-flycheck-normalize-target-kind (kinds)
+ "Return the normalized target name from KIND.
+KIND is a list of target name as returned by `cargo metadata',
+which do not necessarily correspond to to target names that can
+be passed as argument to `cargo rustc'.
+The normalization returns a valid cargo target based on KINDS."
+ ;; Assumption: we only care about the first kind name. Multiple kinds only
+ ;; seem to happen for library crate types, and those all maps to the same
+ ;; `lib' target.
+ (pcase (car kinds)
+ (`"dylib" "lib")
+ (`"rlib" "lib")
+ (`"staticlib" "lib")
+ (`"cdylib" "lib")
+ (`"proc-macro" "lib")
+ (_ (car kinds))))
+
+;;;###autoload
+(defun rustic-flycheck-setup ()
+ "Setup Rust in Flycheck.
+
+If the current file is part of a Cargo project, configure
+Flycheck according to the Cargo project layout."
+ (interactive)
+ ;; We should avoid raising any error in this function, as in combination
+ ;; with `global-flycheck-mode' it will render Emacs unusable (see
+ ;; https://github.com/flycheck/flycheck-rust/issues/40#issuecomment-253760883).
+ (with-demoted-errors "Error in rustic-flycheck-setup: %S"
+ (-when-let* ((file-name (buffer-file-name))
+ (target (rustic-flycheck-find-cargo-target file-name)))
+ (let-alist target
+ (setq-local flycheck-rust-features .required-features)
+ (setq-local flycheck-rust-crate-type .kind)
+ (setq-local flycheck-rust-binary-name .name)))))
+
+(flycheck-define-checker rustic-clippy
+ "A Rust syntax checker using clippy.
+
+See URL `https://github.com/rust-lang-nursery/rust-clippy'."
+ :command ("cargo" "clippy" (eval (split-string rustic-flycheck-clippy-params)))
+ :error-parser flycheck-parse-cargo-rustc
+ :error-filter flycheck-rust-error-filter
+ :error-explainer flycheck-rust-error-explainer
+ :modes rustic-mode
+ :predicate flycheck-buffer-saved-p
+ :enabled (lambda ()
+ (and (flycheck-rust-cargo-has-command-p "clippy")
+ (flycheck-rust-manifest-directory)))
+ :working-directory (lambda (_) (flycheck-rust-manifest-directory))
+ :verify
+ (lambda (_)
+ (and buffer-file-name
+ (let ((has-toml (flycheck-rust-manifest-directory))
+ (has-clippy (flycheck-rust-cargo-has-command-p "clippy")))
+ (list
+ (flycheck-verification-result-new
+ :label "Clippy"
+ :message (if has-clippy "Found"
+ "Cannot find the `cargo clippy' command")
+ :face (if has-clippy 'success '(bold warning)))
+ (flycheck-verification-result-new
+ :label "Cargo.toml"
+ :message (if has-toml "Found" "Missing")
+ :face (if has-toml 'success '(bold warning))))))))
+
+(add-hook 'rustic-mode-hook 'flycheck-mode)
+(add-hook 'flycheck-mode-hook #'rustic-flycheck-setup)
+
+;; turn off flymake
+(add-hook 'rustic-mode-hook 'flymake-mode-off)
+
+;;; _
+(provide 'rustic-flycheck)
+;;; rustic-flycheck.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-interaction.el b/emacs.d/elpa/rustic-20210609.1900/rustic-interaction.el
new file mode 100644
index 0000000..b0819de
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-interaction.el
@@ -0,0 +1,425 @@
+;;; rustic-interaction.el --- Common interactive functions -*-lexical-binding: t-*-
+
+;;; Code:
+
+(require 'newcomment)
+
+(require 'rustic)
+
+;;; Indent Line
+
+(defun rustic-rewind-to-beginning-of-current-level-expr ()
+ (let ((current-level (rustic-paren-level)))
+ (back-to-indentation)
+ (when (looking-at "->")
+ (rustic-rewind-irrelevant)
+ (back-to-indentation))
+ (while (> (rustic-paren-level) current-level)
+ (backward-up-list)
+ (back-to-indentation))
+ ;; When we're in the where clause, skip over it. First find out the start
+ ;; of the function and its paren level.
+ (let ((function-start nil) (function-level nil))
+ (save-excursion
+ (rustic-beginning-of-defun)
+ (back-to-indentation)
+ ;; Avoid using multiple-value-bind
+ (setq function-start (point)
+ function-level (rustic-paren-level)))
+ ;; On a where clause
+ (when (or (rustic-looking-at-where)
+ ;; or in one of the following lines, e.g.
+ ;; where A: Eq
+ ;; B: Hash <- on this line
+ (and (save-excursion
+ (rustic-rewind-to-where function-start))
+ (= current-level function-level)))
+ (goto-char function-start)))))
+
+(defun rustic-align-to-expr-after-brace ()
+ (save-excursion
+ (forward-char)
+ ;; We don't want to indent out to the open bracket if the
+ ;; open bracket ends the line
+ (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$"))
+ (when (looking-at "[[:space:]]")
+ (forward-word 1)
+ (backward-word 1))
+ (current-column))))
+
+(defun rustic-align-to-method-chain ()
+ (save-excursion
+ ;; for method-chain alignment to apply, we must be looking at
+ ;; another method call or field access or something like
+ ;; that. This avoids rather "eager" jumps in situations like:
+ ;;
+ ;; {
+ ;; something.foo()
+ ;; <indent>
+ ;;
+ ;; Without this check, we would wind up with the cursor under the
+ ;; `.`. In an older version, I had the inverse of the current
+ ;; check, where we checked for situations that should NOT indent,
+ ;; vs checking for the one situation where we SHOULD. It should be
+ ;; clear that this is more robust, but also I find it mildly less
+ ;; annoying to have to press tab again to align to a method chain
+ ;; than to have an over-eager indent in all other cases which must
+ ;; be undone via tab.
+
+ (when (looking-at (concat "\s*\." rustic-re-ident))
+ (forward-line -1)
+ (end-of-line)
+ ;; Keep going up (looking for a line that could contain a method chain)
+ ;; while we're in a comment or on a blank line. Stop when the paren
+ ;; level changes.
+ (let ((level (rustic-paren-level)))
+ (while (and (or (rustic-in-str-or-cmnt)
+ ;; Only whitespace (or nothing) from the beginning to
+ ;; the end of the line.
+ (looking-back "^\s*" (point-at-bol)))
+ (= (rustic-paren-level) level))
+ (forward-line -1)
+ (end-of-line)))
+
+ (let
+ ;; skip-dot-identifier is used to position the point at the
+ ;; `.` when looking at something like
+ ;;
+ ;; foo.bar
+ ;; ^ ^
+ ;; | |
+ ;; | position of point
+ ;; returned offset
+ ;;
+ ((skip-dot-identifier
+ (lambda ()
+ (when (and (rustic-looking-back-ident)
+ (save-excursion
+ (forward-thing 'symbol -1)
+ (= ?. (char-before))))
+ (forward-thing 'symbol -1)
+ (backward-char)
+ (- (current-column) rustic-indent-offset)))))
+ (cond
+ ;; foo.bar(...)
+ ((rustic-looking-back-str ")")
+ (backward-list 1)
+ (funcall skip-dot-identifier))
+
+ ;; foo.bar
+ (t (funcall skip-dot-identifier)))))))
+
+;;;###autoload
+(defun rustic-indent-line ()
+ (interactive)
+ (let ((indent
+ (save-excursion
+ (back-to-indentation)
+ ;; Point is now at beginning of current line
+ (let* ((level (rustic-paren-level))
+ (baseline
+ ;; Our "baseline" is one level out from the indentation of the expression
+ ;; containing the innermost enclosing opening bracket. That
+ ;; way if we are within a block that has a different
+ ;; indentation than this mode would give it, we still indent
+ ;; the inside of it correctly relative to the outside.
+ (if (= 0 level)
+ 0
+ (or
+ (when rustic-indent-method-chain
+ (rustic-align-to-method-chain))
+ (save-excursion
+ (rustic-rewind-irrelevant)
+ (backward-up-list)
+ (rustic-rewind-to-beginning-of-current-level-expr)
+ (+ (current-column) rustic-indent-offset))))))
+ (cond
+ ;; Indent inside a non-raw string only if the the previous line
+ ;; ends with a backslash that is inside the same string
+ ((nth 3 (syntax-ppss))
+ (let*
+ ((string-begin-pos (nth 8 (syntax-ppss)))
+ (end-of-prev-line-pos (when (> (line-number-at-pos) 1)
+ (save-excursion
+ (forward-line -1)
+ (end-of-line)
+ (point)))))
+ (when
+ (and
+ ;; If the string begins with an "r" it's a raw string and
+ ;; we should not change the indentation
+ (/= ?r (char-after string-begin-pos))
+
+ ;; If we're on the first line this will be nil and the
+ ;; rest does not apply
+ end-of-prev-line-pos
+
+ ;; The end of the previous line needs to be inside the
+ ;; current string...
+ (> end-of-prev-line-pos string-begin-pos)
+
+ ;; ...and end with a backslash
+ (= ?\\ (char-before end-of-prev-line-pos)))
+
+ ;; Indent to the same level as the previous line, or the
+ ;; start of the string if the previous line starts the string
+ (if (= (line-number-at-pos end-of-prev-line-pos)
+ (line-number-at-pos string-begin-pos))
+ ;; The previous line is the start of the string.
+ ;; If the backslash is the only character after the
+ ;; string beginning, indent to the next indent
+ ;; level. Otherwise align with the start of the string.
+ (if (> (- end-of-prev-line-pos string-begin-pos) 2)
+ (save-excursion
+ (goto-char (+ 1 string-begin-pos))
+ (current-column))
+ baseline)
+
+ ;; The previous line is not the start of the string, so
+ ;; match its indentation.
+ (save-excursion
+ (goto-char end-of-prev-line-pos)
+ (back-to-indentation)
+ (current-column))))))
+
+ ;; A function return type is indented to the corresponding
+ ;; function arguments, if -to-arguments is selected.
+ ((and rustic-indent-return-type-to-arguments
+ (looking-at "->"))
+ (save-excursion
+ (backward-list)
+ (or (rustic-align-to-expr-after-brace)
+ (+ baseline rustic-indent-offset))))
+
+ ;; A closing brace is 1 level unindented
+ ((looking-at "[]})]") (- baseline rustic-indent-offset))
+
+ ;; Doc comments in /** style with leading * indent to line up the *s
+ ((and (nth 4 (syntax-ppss)) (looking-at "*"))
+ (+ 1 baseline))
+
+ ;; When the user chose not to indent the start of the where
+ ;; clause, put it on the baseline.
+ ((and (not rustic-indent-where-clause)
+ (rustic-looking-at-where))
+ baseline)
+
+ ;; If we're in any other token-tree / sexp, then:
+ (t
+ (or
+ ;; If we are inside a pair of braces, with something after the
+ ;; open brace on the same line and ending with a comma, treat
+ ;; it as fields and align them.
+ (when (> level 0)
+ (save-excursion
+ (rustic-rewind-irrelevant)
+ (backward-up-list)
+ ;; Point is now at the beginning of the containing set of braces
+ (rustic-align-to-expr-after-brace)))
+
+ ;; When where-clauses are spread over multiple lines, clauses
+ ;; should be aligned on the type parameters. In this case we
+ ;; take care of the second and following clauses (the ones
+ ;; that don't start with "where ")
+ (save-excursion
+ ;; Find the start of the function, we'll use this to limit
+ ;; our search for "where ".
+ (let ((function-start nil) (function-level nil))
+ (save-excursion
+ ;; If we're already at the start of a function,
+ ;; don't go back any farther. We can easily do
+ ;; this by moving to the end of the line first.
+ (end-of-line)
+ (rustic-beginning-of-defun)
+ (back-to-indentation)
+ ;; Avoid using multiple-value-bind
+ (setq function-start (point)
+ function-level (rustic-paren-level)))
+ ;; When we're not on a line starting with "where ", but
+ ;; still on a where-clause line, go to "where "
+ (when (and
+ (not (rustic-looking-at-where))
+ ;; We're looking at something like "F: ..."
+ (looking-at (concat rustic-re-ident ":"))
+ ;; There is a "where " somewhere after the
+ ;; start of the function.
+ (rustic-rewind-to-where function-start)
+ ;; Make sure we're not inside the function
+ ;; already (e.g. initializing a struct) by
+ ;; checking we are the same level.
+ (= function-level level))
+ ;; skip over "where"
+ (forward-char 5)
+ ;; Unless "where" is at the end of the line
+ (if (eolp)
+ ;; in this case the type parameters bounds are just
+ ;; indented once
+ (+ baseline rustic-indent-offset)
+ ;; otherwise, skip over whitespace,
+ (skip-chars-forward "[:space:]")
+ ;; get the column of the type parameter and use that
+ ;; as indentation offset
+ (current-column)))))
+
+ (progn
+ (back-to-indentation)
+ ;; Point is now at the beginning of the current line
+ (if (or
+ ;; If this line begins with "else" or "{", stay on the
+ ;; baseline as well (we are continuing an expression,
+ ;; but the "else" or "{" should align with the beginning
+ ;; of the expression it's in.)
+ ;; Or, if this line starts a comment, stay on the
+ ;; baseline as well.
+ (looking-at "\\<else\\>\\|{\\|/[/*]")
+
+ ;; If this is the start of a top-level item,
+ ;; stay on the baseline.
+ (looking-at rustic-top-item-beg-re)
+
+ (save-excursion
+ (rustic-rewind-irrelevant)
+ ;; Point is now at the end of the previous line
+ (or
+ ;; If we are at the start of the buffer, no
+ ;; indentation is needed, so stay at baseline...
+ (= (point) 1)
+ ;; ..or if the previous line ends with any of these:
+ ;; { ? : ( , ; [ }
+ ;; then we are at the beginning of an
+ ;; expression, so stay on the baseline...
+ (looking-back "[(,:;?[{}]\\|[^|]|" (- (point) 2))
+ ;; or if the previous line is the end of an
+ ;; attribute, stay at the baseline...
+ (progn
+ (rustic-rewind-to-beginning-of-current-level-expr)
+ (looking-at "#")))))
+ baseline
+
+ ;; Otherwise, we are continuing the same
+ ;; expression from the previous line, so add one
+ ;; additional indent level
+ (+ baseline rustic-indent-offset))))))))))
+
+ (when indent
+ ;; If we're at the beginning of the line (before or at the current
+ ;; indentation), jump with the indentation change. Otherwise, save the
+ ;; excursion so that adding the indentations will leave us at the
+ ;; equivalent position within the line to where we were before.
+ (if (<= (current-column) (current-indentation))
+ (indent-line-to indent)
+ (save-excursion (indent-line-to indent))))))
+
+;;; Miscellaneous
+
+;;;###autoload
+(defun rustic-promote-module-into-dir ()
+ "Promote the module file visited by the current buffer into its own directory.
+
+For example, if the current buffer is visiting the file `foo.rs',
+then this function creates the directory `foo' and renames the
+file to `foo/mod.rs'. The current buffer will be updated to
+visit the new file."
+ (interactive)
+ (let ((filename (buffer-file-name)))
+ (if (not filename)
+ (message "Buffer is not visiting a file.")
+ (if (string-equal (file-name-nondirectory filename) "mod.rs")
+ (message "Won't promote a module file already named mod.rs.")
+ (let* ((basename (file-name-sans-extension
+ (file-name-nondirectory filename)))
+ (mod-dir (file-name-as-directory
+ (concat (file-name-directory filename) basename)))
+ (new-name (concat mod-dir "mod.rs")))
+ (mkdir mod-dir t)
+ (rename-file filename new-name 1)
+ (set-visited-file-name new-name))))))
+
+(defun rustic-docstring-dwim ()
+ "Use `comment-dwim' to make a docstring."
+ (interactive)
+ (let ((comment-start "/// "))
+ (call-interactively 'comment-dwim)))
+
+;;;###autoload
+(defun rustic-open-dependency-file ()
+ "Open the 'Cargo.toml' file at the project root if the current buffer is
+visiting a project."
+ (interactive)
+ (let ((workspace (rustic-buffer-workspace t)))
+ (if workspace
+ (find-file (concat workspace "/Cargo.toml"))
+ (message "The current buffer is not inside a rust project!"))))
+
+;;; Defun Motions
+
+(defvar rustic-func-item-beg-re
+ (concat "\\s-*\\(?:priv\\|pub\\)?\\s-*\\(?:async\\)?\\s-*"
+ (regexp-opt '("fn")))
+ "Start of a rust function.")
+
+(defun rustic-beginning-of-function ()
+ "Move to beginning of rust function at point."
+ (rustic-beginning-of-defun nil rustic-func-item-beg-re))
+
+;; TODO: since we are using `rustic-top-item-beg-re' this function actually sets
+;; the point where it finds the first item of the list
+;; this function should be renamed or documented correctly
+;;;###autoload
+(defun rustic-beginning-of-defun (&optional arg regex)
+ "Move backward to the beginning of the current defun.
+
+With ARG, move backward multiple defuns. Negative ARG means
+move forward.
+
+This is written mainly to be used as `beginning-of-defun-function' for Rust.
+Don't move to the beginning of the line. `beginning-of-defun',
+which calls this, does that afterwards."
+ (interactive "p")
+ (let* ((arg (or arg 1))
+ (magnitude (abs arg))
+ (sign (if (< arg 0) -1 1)))
+ ;; If moving forward, don't find the defun we might currently be
+ ;; on.
+ (when (< sign 0)
+ (end-of-line))
+ (catch 'done
+ (dotimes (_ magnitude)
+ ;; Search until we find a match that is not in a string or comment.
+ (while (if (re-search-backward
+ (concat "^\\(" (or regex rustic-top-item-beg-re) "\\)")
+ nil 'move sign)
+ (rustic-in-str-or-cmnt)
+ ;; Did not find it.
+ (throw 'done nil)))))
+ t))
+
+;;;###autoload
+(defun rustic-end-of-defun ()
+ "Move forward to the next end of defun.
+
+With argument, do it that many times.
+Negative argument -N means move back to Nth preceding end of defun.
+
+Assume that this is called after beginning-of-defun. So point is
+at the beginning of the defun body.
+
+This is written mainly to be used as `end-of-defun-function' for Rust."
+ (interactive)
+ ;; Find the opening brace
+ (if (re-search-forward "[{]" nil t)
+ (progn
+ (goto-char (match-beginning 0))
+ ;; Go to the closing brace
+ (condition-case nil
+ (forward-sexp)
+ (scan-error
+ ;; The parentheses are unbalanced; instead of being unable
+ ;; to fontify, just jump to the end of the buffer
+ (goto-char (point-max)))))
+ ;; There is no opening brace, so consider the whole buffer to be one "defun"
+ (goto-char (point-max))))
+
+;;; _
+(provide 'rustic-interaction)
+;;; rustic-interaction.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-lsp.el b/emacs.d/elpa/rustic-20210609.1900/rustic-lsp.el
new file mode 100644
index 0000000..471e7cc
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-lsp.el
@@ -0,0 +1,170 @@
+;;; rustic-lsp.el --- Support for lsp -*- lexical-binding:t -*-
+;;; Commentary:
+
+;; This library implements support for "lsp".
+
+;;; Code:
+
+(require 'rustic-rustfmt)
+
+;;; Options
+
+;; FIXME This is non-idomatic. This option should be replaced with
+;; documentation that instructs the user to add the setup function
+;; themselves, iff so desired.
+(defcustom rustic-lsp-setup-p t
+ "Setup LSP related stuff automatically.
+If this is non-nil (the default), then loading `rustic-lsp' adds
+`rustic-setup-lsp' to `rustic-mode-hook'. If you don't want that
+then you must set this to nil before loading `rustic-lsp'."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'rustic)
+(when rustic-lsp-setup-p
+ (add-hook 'rustic-mode-hook 'rustic-setup-lsp))
+
+(defcustom rustic-lsp-server 'rust-analyzer
+ "Choose your LSP server."
+ :type '(choice (const :tag "rls" rls)
+ (const :tag "rust-analyzer" rust-analyzer))
+ :group 'rustic)
+
+(define-obsolete-variable-alias 'rustic-rls-pkg 'rustic-lsp-client "Rustic 0.18")
+(defcustom rustic-lsp-client 'lsp-mode
+ "Emacs package for interaction with the language server."
+ :type '(choice (const :tag "eglot" eglot)
+ (const :tag "lsp-mode" lsp-mode)
+ (const :tag "No LSP client" nil))
+ :group 'rustic)
+
+(defcustom rustic-lsp-format nil
+ "Allow formatting through lsp server."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'rustic)
+
+(defcustom rustic-analyzer-command '("rust-analyzer")
+ "Command for calling rust analyzer."
+ :type '(repeat (string))
+ :group 'rustic)
+
+;;; Common
+
+(defun rustic-setup-lsp ()
+ "Setup LSP client. If client isn't installed, offer to install it."
+ (let ((client rustic-lsp-client))
+ (cond ((eq client nil)
+ nil)
+ ((require client nil t)
+ (if (eq client 'eglot)
+ (eglot-ensure)
+ (rustic-lsp-mode-setup)
+ (lsp)))
+ (t
+ (rustic-install-lsp-client-p client)))))
+
+;;; lsp support
+
+(defvar lsp-rust-analyzer-macro-expansion-method)
+(defvar lsp-rust-analyzer-server-command)
+(defvar lsp-rust-server)
+(declare-function lsp "lsp-mode" (&optional arg))
+(declare-function lsp-rust-switch-server "lsp-rust" (lsp-server))
+(declare-function lsp-workspace-folders-add "lsp-rust" (project-root))
+(declare-function lsp-workspace-root "lsp-mode" (&optional path))
+
+(defun rustic-lsp-mode-setup ()
+ "When changing the `lsp-rust-server', it's also necessary to update the priorities
+with `lsp-rust-switch-server'."
+ (require 'lsp-rust)
+ (require 'lsp-modeline)
+ (lsp-workspace-folders-add (rustic-buffer-workspace))
+ (setq lsp-rust-server rustic-lsp-server)
+ (setq lsp-rust-analyzer-server-command rustic-analyzer-command)
+ (lsp-rust-switch-server rustic-lsp-server))
+
+(defun rustic-install-lsp-client-p (lsp-client)
+ "Ask user whether to install missing LSP-CLIENT."
+ (if (yes-or-no-p (format "%s not found. Install it ?" lsp-client))
+ (condition-case err
+ (progn
+ (package-refresh-contents)
+ (package-install lsp-client)
+ (require lsp-client)
+ (rustic-setup-lsp))
+ (error err))
+ (message "No LSP server running.")))
+
+;;; eglot support
+
+(defvar eglot-ignored-server-capabilites)
+(defvar eglot-ignored-server-capabilites)
+(defvar eglot-server-programs)
+(defvar eglot-server-programs)
+(declare-function eglot-ensure "eglot" ())
+
+(defun rustic-setup-eglot ()
+ "Configure eglot for rustic."
+ (require 'eglot)
+ (if (equal rustic-lsp-server 'rls)
+ ;; add rustic to `eglot-server-programs'
+ (let ((rls '(rustic-mode . (eglot-rls "rls"))))
+ (unless (member rls eglot-server-programs)
+ (setq eglot-server-programs
+ `(,rls
+ ;; replace rust-mode with rustic
+ ,@(-remove-first (lambda (mode)
+ (when (symbolp (car mode))
+ (eq (car mode) 'rust-mode)))
+ eglot-server-programs)))))
+ (add-to-list 'eglot-server-programs `(rustic-mode . ,rustic-analyzer-command)))
+ ;; don't allow formatting with rls
+ (unless rustic-lsp-format
+ (let ((feature :documentFormattingProvider))
+ (unless (-contains? eglot-ignored-server-capabilites feature)
+ (add-to-list 'eglot-ignored-server-capabilites feature)))))
+
+(with-eval-after-load 'eglot
+ (rustic-setup-eglot))
+
+;;; rustic-macro-expansion-mode
+
+(setq lsp-rust-analyzer-macro-expansion-method 'rustic-analyzer-macro-expand)
+
+(define-derived-mode rustic-macro-expansion-mode special-mode "Rust"
+ :group 'rustic
+ :syntax-table rustic-mode-syntax-table
+ ;; Fonts
+ (setq-local font-lock-defaults '(rustic-font-lock-keywords
+ nil nil nil nil
+ (font-lock-syntactic-face-function
+ . rustic-syntactic-face-function))))
+
+;;;###autoload
+(defun rustic-analyzer-macro-expand (result)
+ "Default method for displaying macro expansion results."
+ (interactive)
+ (let* ((root (lsp-workspace-root default-directory))
+ (buf (get-buffer-create
+ (format "*rust-analyzer macro expansion %s*" root))))
+ (with-current-buffer buf
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ ;; wrap expanded macro in a main function so we can run rustfmt
+ (insert "fn main()")
+ ;; rustfmt complains about $s
+ (insert (replace-regexp-in-string "\\$" "" result))
+ (rustic-macro-expansion-mode)
+ (rustic-format-buffer)
+ (with-current-buffer buf
+ (save-excursion
+ (goto-char (point-min))
+ (delete-region (point-min) (line-end-position))
+ (goto-char (point-max))
+ (forward-line -1)
+ (delete-region (line-beginning-position) (point-max))))))
+ (display-buffer buf)))
+
+;;; _
+(provide 'rustic-lsp)
+;;; rustic-lsp.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-pkg.el b/emacs.d/elpa/rustic-20210609.1900/rustic-pkg.el
new file mode 100644
index 0000000..64c1a7d
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-pkg.el
@@ -0,0 +1,20 @@
+(define-package "rustic" "20210609.1900" "Rust development environment"
+ '((emacs "26.1")
+ (dash "2.13.0")
+ (f "0.18.2")
+ (let-alist "1.0.4")
+ (markdown-mode "2.3")
+ (project "0.3.0")
+ (s "1.10.0")
+ (seq "2.3")
+ (spinner "1.7.3")
+ (xterm-color "1.6"))
+ :commit "6ca73bb3cce4d1db3c4f91efb83b63227eb712d1" :authors
+ '(("Mozilla"))
+ :maintainer
+ '("Mozilla")
+ :keywords
+ '("languages"))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-playpen.el b/emacs.d/elpa/rustic-20210609.1900/rustic-playpen.el
new file mode 100644
index 0000000..82e38b5
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-playpen.el
@@ -0,0 +1,61 @@
+;;; rustic-playpen.el --- Support for playpen -*- lexical-binding:t -*-
+;;; Commentary:
+;;; Code:
+
+(require 'org-element)
+(require 'url)
+
+;;; Options
+
+(defcustom rustic-playpen-url-format "https://play.rust-lang.org/?code=%s"
+ "Format string to use when submitting code to the playpen."
+ :type 'string
+ :group 'rustic)
+
+(defcustom rustic-shortener-url-format "https://is.gd/create.php?format=simple&url=%s"
+ "Format string to use for creating the shortened link of a playpen submission."
+ :type 'string
+ :group 'rustic)
+
+;;; Commands
+
+;;;###autoload
+(defun rustic-playpen (begin end)
+ "Create a shareable URL for the contents of the current region,
+src-block or buffer on the Rust playpen."
+ (interactive "r")
+ (let (data)
+ (cond
+ ((region-active-p)
+ (setq data (buffer-substring begin end)))
+ ((org-in-src-block-p)
+ (setq data (org-element-property :value (org-element-at-point))))
+ (t
+ (setq data (buffer-substring (point-min) (point-max)))))
+ (let* ((escaped-data (url-hexify-string data))
+ (escaped-playpen-url (url-hexify-string
+ (format rustic-playpen-url-format
+ escaped-data))))
+ (if (> (length escaped-playpen-url) 5000)
+ (error "encoded playpen data exceeds 5000 character limit (length %s)"
+ (length escaped-playpen-url))
+ (let ((shortener-url (format rustic-shortener-url-format escaped-playpen-url))
+ (url-request-method "POST"))
+ (url-retrieve shortener-url
+ (lambda (state)
+ ;; filter out the headers etc. included at the
+ ;; start of the buffer: the relevant text
+ ;; (shortened url or error message) is exactly
+ ;; the last line.
+ (goto-char (point-max))
+ (let ((last-line (thing-at-point 'line t))
+ (err (plist-get state :error)))
+ (kill-buffer)
+ (if err
+ (error "failed to shorten playpen url: %s" last-line)
+ (let ((URL (read-from-minibuffer "Playpen URL: " last-line)))
+ (browse-url URL)))))))))))
+
+;;; _
+(provide 'rustic-playpen)
+;;; rustic-playpen.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-popup.el b/emacs.d/elpa/rustic-20210609.1900/rustic-popup.el
new file mode 100644
index 0000000..c8864eb
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-popup.el
@@ -0,0 +1,241 @@
+;;; rustic-popup.el --- Cargo popup -*-lexical-binding: t-*-
+
+;;; Commentary:
+
+;; Provides magit like popup.
+
+;;; Code:
+
+(require 'rustic-cargo)
+
+;;; Customization
+
+(defcustom rustic-popup-commands
+ '((?b "build" build)
+ (?f "fmt" fmt)
+ (?r "run" run)
+ (?c "clippy" clippy)
+ (?o "outdated" outdated)
+ (?e "clean" clean)
+ (?k "check" check)
+ (?t "test" test)
+ (?d "doc" doc))
+ "List of commands that are displayed in the popup.
+The first element of each list contains a command's binding."
+ :type 'list
+ :group 'rustic-popup)
+
+(define-obsolete-face-alias 'rustic-popup-key-face
+ 'rustic-popup-key "1.2")
+(define-obsolete-face-alias 'rustic-popup-section-face
+ 'rustic-popup-section "1.2")
+
+(defface rustic-popup-key
+ '((t (:foreground "DeepSkyBlue")))
+ "Face used for command shortcuts."
+ :group 'rustic)
+
+(defface rustic-popup-section
+ '((t (:foreground "#f74c00")))
+ "Face used for popup section description."
+ :group 'rustic)
+
+;;; Popup Mode
+
+(defvar rustic-popup-buffer-name "rustic-popup-buffer"
+ "Buffer name for rustic popup buffers.")
+
+(defvar rustic-popup-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [remap self-insert-command] 'rustic-popup-invoke-popup-action)
+ (define-key map (kbd "g") 'rustic-recompile)
+ (define-key map (kbd "RET") 'rustic-popup-default-action)
+ (define-key map (kbd "<tab>") 'rustic-popup-default-action)
+ (define-key map (kbd "h") 'rustic-popup-cargo-command-help)
+ (define-key map (kbd "q") 'kill-buffer-and-window)
+ map)
+ "Keymap for rustic popup buffers.")
+
+(define-derived-mode rustic-popup-mode fundamental-mode "RusticPopup"
+ "Mode for rustic popup buffers."
+ (setq truncate-lines t)
+ (setq buffer-read-only t)
+ (setq-local scroll-margin 0))
+
+(defun rustic-popup-insert-backtrace ()
+ "Insert backtrace section."
+ (let ((inhibit-read-only t)
+ (prop (lambda (s)
+ (propertize s 'face 'rustic-popup-section))))
+ (insert (funcall prop "Backtrace: "))
+ (cond
+ ((string= rustic-compile-backtrace "0")
+ (insert " " (funcall prop "0") " | 1 | full"))
+ ((string= rustic-compile-backtrace "1")
+ (insert " 0 | " (funcall prop "1") " | full"))
+ ((string= rustic-compile-backtrace "full")
+ (insert " 0 | 1 | " (funcall prop "full")))))
+ (insert "\n\n"))
+
+(defun rustic-popup-insert-contents (buf)
+ "Insert popup buffer contents."
+ (let ((inhibit-read-only t))
+ (with-current-buffer buf
+ (erase-buffer)
+ (rustic-popup-mode)
+ (rustic-popup-insert-backtrace)
+ (insert (propertize "Commands: " 'face 'rustic-popup-section) "\n")
+ (insert " " (propertize "g" 'face 'rustic-popup-key)
+ " " "recompile" " " "\""
+ (or compilation-arguments rustic-compile-command)
+ "\"" "\n\n")
+ (dolist (command rustic-popup-commands)
+ (insert "\s")
+ (insert (propertize (char-to-string (nth 0 command))
+ 'face 'rustic-popup-key))
+ (insert "\s\s\s\s\s\s")
+ (insert (nth 1 command))
+ (when (and (string= (nth 1 command) "test")
+ (> (length rustic-test-arguments) 0))
+ (insert " " "\"" rustic-test-arguments "\""))
+ (insert "\n"))
+ (goto-char (point-min)))))
+
+;;;###autoload
+(defun rustic-popup ()
+ "Setup popup.
+If directory is not in a rust project call `read-directory-name'."
+ (interactive)
+ (let ((func (lambda ()
+ (let ((buf (get-buffer-create rustic-popup-buffer-name))
+ (win (split-window-below))
+ (inhibit-read-only t))
+ (rustic-popup-insert-contents buf)
+ (set-window-buffer win buf)
+ (select-window win)
+ (fit-window-to-buffer)
+ (set-window-text-height win (+ (window-height) 1))))))
+ (if (rustic-buffer-workspace t)
+ (funcall func)
+ (let ((dir (read-directory-name "Rust project:")))
+ (let ((default-directory dir))
+ (if (rustic-buffer-workspace t)
+ (funcall func)
+ (message "Not a rust project.")))))))
+
+;;; Interactive
+
+;;;###autoload
+(defun rustic-popup-invoke-popup-action (event)
+ "Execute commands which are listed in `rustic-popup-commands'."
+ (interactive (list last-command-event))
+ (save-excursion
+ (let ((char (char-to-string event)))
+ (save-match-data
+ (goto-char (point-min))
+ (when (re-search-forward (concat "\s" char "\s"))
+ (goto-char (match-beginning 0)))))
+ (let* ((command (cadr (split-string
+ (buffer-substring-no-properties
+ (point) (line-end-position)))))
+ (c (intern (concat "rustic-cargo-" command))))
+ (if (commandp c)
+ (call-interactively c)
+ (call-interactively 'rustic-compile (concat "cargo " command))))))
+
+;;;###autoload
+(defun rustic-popup-default-action ()
+ "Change backtrace and `compilation-arguments' when executed on
+corresponding line."
+ (interactive)
+ (let ((inhibit-read-only t))
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (cond
+ ((looking-at "Backtrace:")
+ (cond
+ ((string= rustic-compile-backtrace "0")
+ (setq rustic-compile-backtrace "1"))
+ ((string= rustic-compile-backtrace "1")
+ (setq rustic-compile-backtrace "full"))
+ ((string= rustic-compile-backtrace "full")
+ (setq rustic-compile-backtrace "0")))
+ (rustic-popup-insert-contents (current-buffer)))
+ ((search-forward-regexp "\srecompile\s" (line-end-position) t)
+ (setq compilation-arguments
+ (read-string "Compilation arguments: "
+ (or compilation-arguments rustic-compile-command)))
+ (rustic-popup-insert-contents (current-buffer)))
+ ((search-forward-regexp "\stest" (line-end-position) t)
+ (setq rustic-test-arguments
+ (read-string "Cargo test arguments: " rustic-test-arguments))
+ (rustic-popup-insert-contents (current-buffer)))
+ (t
+ (message "No default action for line."))))))
+
+;;; Help Popup
+
+(defvar rustic-popup-help-buffer-name "rustic-popup-help-buffer"
+ "Buffer name for rustic popup help buffers.")
+
+(defvar rustic-popup-help-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "q") 'rustic-popup-kill-help-buffer)
+ map)
+ "Keymap for rustic popup help buffers.")
+
+(define-derived-mode rustic-popup-help-mode fundamental-mode "RusticHelpPopup"
+ "Mode for rustic popup help buffers."
+ (setq truncate-lines t)
+ (setq buffer-read-only t)
+ (setq-local scroll-margin 0))
+
+;;;###autoload
+(defun rustic-popup-cargo-command-help ()
+ "Display help buffer for cargo command at point."
+ (interactive)
+ (let (command)
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (setq command (cadr (split-string
+ (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position))))))
+ (let* ((string (rustic-popup-help-flags command))
+ (inhibit-read-only t))
+ (if (not (and (> (length command) 0)
+ (> (length (split-string string "\n")) 0)))
+ (message "No help information for command at point.")
+ (rustic-popup-setup-help-popup string)))))
+
+(defun rustic-popup-help-flags (command)
+ "Get flags of COMMAND."
+ (let ((string (shell-command-to-string (format "cargo %s -h" command)))
+ flags)
+ (dolist (s (split-string string "\n"))
+ (when (and (not (string-match "^\s+\-h" s))
+ (string-match "^\s+\-" s))
+ (setq flags (concat flags s "\n"))))
+ flags))
+
+(defun rustic-popup-setup-help-popup (string)
+ "Switch to help buffer."
+ (let ((buf (get-buffer-create rustic-popup-help-buffer-name)))
+ (switch-to-buffer buf)
+ (erase-buffer)
+ (rustic-popup-help-mode)
+ (insert string)
+ (fit-window-to-buffer)
+ (set-window-text-height (selected-window) (+ (window-height) 1))
+ (goto-char (point-min))))
+
+;;;###autoload
+(defun rustic-popup-kill-help-buffer ()
+ "Kill popup help buffer and switch to popup buffer."
+ (interactive)
+ (switch-to-buffer rustic-popup-buffer-name)
+ (fit-window-to-buffer)
+ (set-window-text-height (selected-window) (+ (window-height) 1)))
+
+;;; _
+(provide 'rustic-popup)
+;;; rustic-popup.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-racer.el b/emacs.d/elpa/rustic-20210609.1900/rustic-racer.el
new file mode 100644
index 0000000..7910183
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-racer.el
@@ -0,0 +1,515 @@
+;;; rustic-racer.el --- Racer support -*-lexical-binding: t-*-
+
+;;; Code:
+
+(require 'f)
+(require 's)
+
+(require 'button)
+(require 'etags)
+(require 'help-mode)
+(require 'thingatpt)
+
+(require 'rustic)
+
+(defvar rustic-racer-args nil)
+
+(defgroup racer nil
+ "Docs browsing for Rust via racer."
+ :link '(url-link "https://github.com/racer-rust/emacs-racer/")
+ :group 'rustic-mode)
+
+;;; Customization
+
+(defcustom rustic-racer-cmd
+ (or (executable-find "racer")
+ (f-expand "~/.cargo/bin/racer")
+ "/usr/local/bin/racer")
+ "Path to the racer binary."
+ :type 'file
+ :group 'racer)
+
+(defcustom rustic-racer-rust-src-path
+ (or
+ (getenv "RUST_SRC_PATH")
+ (when (executable-find "rustc")
+ (let* ((sysroot (s-trim-right
+ (shell-command-to-string
+ (format "%s --print sysroot" (executable-find "rustc")))))
+ (src-path (f-join sysroot "lib/rustlib/src/rust/src")))
+ (when (file-exists-p src-path)
+ src-path)
+ src-path))
+ "/usr/local/src/rust/src")
+
+ "Path to the rust source tree.
+If nil, we will query $RUST_SRC_PATH at runtime.
+If $RUST_SRC_PATH is not set, look for rust source
+in rustup's install directory."
+ :type 'file
+ :group 'racer)
+
+(defcustom rustic-racer-cargo-home
+ (or
+ (getenv "CARGO_HOME")
+ "~/.cargo")
+ "Path to your current cargo home. Usually `~/.cargo'.
+If nil, we will query $CARGO_HOME at runtime."
+ :type 'file
+ :group 'racer)
+
+;;; Faces
+
+(define-obsolete-face-alias 'rustic-racer-help-heading-face
+ 'rustic-racer-help-heading "1.2")
+
+(defface rustic-racer-help-heading
+ '((t :weight bold))
+ "Face for markdown headings in *Racer Help* buffers.")
+
+(defface rustic-racer-tooltip
+ '((((min-colors 16777216))
+ :background "#292C33" :foreground "white")
+ (t
+ :background "black" :foreground "white"))
+ "Face used for the tooltip with `racer-describe-tooltip'")
+
+;;; Help-mode
+
+(defvar rustic-racer-help-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map (make-composed-keymap button-buffer-map
+ special-mode-map))
+ map)
+ "Keymap for racer help mode.")
+
+(define-derived-mode rustic-racer-help-mode fundamental-mode
+ "Racer-Help"
+ "Major mode for *Racer Help* buffers.
+Commands:
+\\{racer-help-mode-map}")
+
+(defun rustic-racer-header (text)
+ "Helper function for adding text properties to TEXT."
+ (propertize text 'face 'rustic-racer-help-heading))
+
+(defun rustic-racer-button-go-to-src (button)
+ (rustic-racer-find-file
+ (button-get button 'path)
+ (button-get button 'line)
+ (button-get button 'column)))
+
+(define-button-type 'racer-src-button
+ 'action 'rustic-racer-button-go-to-src
+ 'follow-link t
+ 'help-echo "Go to definition")
+
+(defun rustic-racer-url-button (text url)
+ "Return a button that opens a browser at URL."
+ (with-temp-buffer
+ (insert-text-button
+ text
+ :type 'help-url
+ 'help-args (list url))
+ (buffer-string)))
+
+(defun rustic-racer-src-button (path line column)
+ "Return a button that navigates to PATH at LINE number and
+COLUMN number."
+ ;; Convert "/foo/bar/baz/foo.rs" to "baz/foo.rs"
+ (let* ((filename (f-filename path))
+ (parent-dir (f-filename (f-parent path)))
+ (short-path (f-join parent-dir filename)))
+ (with-temp-buffer
+ (insert-text-button
+ short-path
+ :type 'racer-src-button
+ 'path path
+ 'line line
+ 'column column)
+ (buffer-string))))
+
+(defun rustic-racer-help-buf (contents)
+ "Create a *Racer Help* buffer with CONTENTS."
+ (let ((buf (get-buffer-create "*Racer Help*"))
+ ;; If the buffer already existed, we need to be able to
+ ;; override `buffer-read-only'.
+ (inhibit-read-only t))
+ (with-current-buffer buf
+ (erase-buffer)
+ (insert contents)
+ (setq buffer-read-only t)
+ (goto-char (point-min))
+ (rustic-racer-help-mode))
+ buf))
+
+;;; Racer
+
+(defvar rustic-racer-prev-state nil)
+
+(defun rustic-racer-call (command &rest args)
+ "Call racer command COMMAND with args ARGS.
+Return stdout if COMMAND exits normally, otherwise show an
+error."
+ (let ((rust-src-path (or rustic-racer-rust-src-path (getenv "RUST_SRC_PATH")))
+ (cargo-home (or rustic-racer-cargo-home (getenv "CARGO_HOME"))))
+ (when (null rust-src-path)
+ (user-error "You need to set `rustic-racer-rust-src-path' or `RUST_SRC_PATH'"))
+ (unless (file-exists-p rust-src-path)
+ (user-error "No such directory: %s. Please set `rustic-racer-rust-src-path' or `RUST_SRC_PATH'"
+ rust-src-path))
+ (let ((default-directory (rustic-buffer-workspace))
+ (process-environment (append (list
+ (format "RUST_SRC_PATH=%s" (expand-file-name rust-src-path))
+ (format "CARGO_HOME=%s" (expand-file-name cargo-home)))
+ process-environment)))
+ (-let [(exit-code stdout _stderr)
+ (rustic-racer-shell-command rustic-racer-cmd (cons command args))]
+ ;; Use `equal' instead of `zero' as exit-code can be a string
+ ;; "Aborted" if racer crashes.
+ (unless (equal 0 exit-code)
+ (user-error "%s exited with %s. `M-x rustic-racer-debug' for more info"
+ rustic-racer-cmd exit-code))
+ stdout))))
+
+(defun rustic-racer-doc (name)
+ "Return a *Racer Help* buffer for the function or type at point.
+If there are multiple candidates at point, use NAME to find the
+correct value."
+ (let ((description (rustic-racer-describe-at-point name)))
+ (when description
+ (let* ((name (plist-get description :name))
+ (raw-docstring (plist-get description :docstring))
+ (docstring (if raw-docstring
+ (rustic-racer-propertize-docstring raw-docstring)
+ "Not documented."))
+ (kind (plist-get description :kind)))
+ (rustic-racer-help-buf
+ (format
+ "%s is %s defined in %s.\n\n%s%s"
+ name
+ (rustic-racer-kind-description kind)
+ (rustic-racer-src-button
+ (plist-get description :path)
+ (plist-get description :line)
+ (plist-get description :column))
+ (if (equal kind "Module")
+ ;; No point showing the 'signature' of modules, which is
+ ;; just their full path.
+ ""
+ (format " %s\n\n" (rustic-racer-syntax-highlight (plist-get description :signature))))
+ docstring))))))
+
+(defun rustic-racer-describe-at-point (name)
+ "Get a description of the symbol at point matching NAME.
+If there are multiple possibilities with this NAME, prompt
+the user to choose."
+ (let* ((output-lines (save-excursion
+ ;; Move to the end of the current symbol, to
+ ;; increase racer accuracy.
+ (skip-syntax-forward "w_")
+ (rustic-racer-call-at-point "complete-with-snippet")))
+ (all-matches (--map (when (s-starts-with-p "MATCH " it)
+ (rustic-racer-split-snippet-match it))
+ output-lines))
+ (relevant-matches (--filter (equal (plist-get it :name) name)
+ all-matches)))
+ (if (> (length relevant-matches) 1)
+ ;; We might have multiple matches with the same name but
+ ;; different types. E.g. Vec::from.
+ (let ((signature
+ (completing-read "Multiple matches: "
+ (--map (plist-get it :signature) relevant-matches))))
+ (--first (equal (plist-get it :signature) signature) relevant-matches))
+ (-first-item relevant-matches))))
+
+(defmacro rustic-racer-with-temporary-file (path-sym &rest body)
+ "Create a temporary file, and bind its path to PATH-SYM.
+Evaluate BODY, then delete the temporary file."
+ (declare (indent 1) (debug (symbolp body)))
+ `(let ((,path-sym (make-temp-file "racer")))
+ (unwind-protect
+ (progn ,@body)
+ (delete-file ,path-sym))))
+
+(defun rustic-racer-call-at-point (command)
+ "Call racer command COMMAND at point of current buffer.
+Return a list of all the lines returned by the command."
+ (rustic-racer-with-temporary-file tmp-file
+ (write-region nil nil tmp-file nil 'silent)
+ (let ((racer-args (list
+ command
+ (number-to-string (line-number-at-pos))
+ (number-to-string (rustic-racer-current-column)))))
+ ;; If this buffer is backed by a file, pass that to racer too.
+ (-when-let (file-name (buffer-file-name (buffer-base-buffer)))
+ (setq rustic-racer-args
+ (append racer-args (list file-name))))
+
+ (setq rustic-racer-args (append rustic-racer-args (list tmp-file)))
+ (s-lines
+ (s-trim-right
+ (apply #'rustic-racer-call rustic-racer-args))))))
+
+(defun rustic-racer-shell-command (program args)
+ "Execute PROGRAM with ARGS.
+Return a list (exit-code stdout stderr)."
+ (rustic-racer-with-temporary-file tmp-file-for-stderr
+ (let (exit-code stdout stderr)
+ ;; Create a temporary buffer for `call-process` to write stdout
+ ;; into.
+ (with-temp-buffer
+ (setq exit-code
+ (apply #'call-process program nil
+ (list (current-buffer) tmp-file-for-stderr)
+ nil args))
+ (setq stdout (buffer-string)))
+ (setq stderr (rustic-racer-slurp tmp-file-for-stderr))
+ (setq rustic-racer-prev-state
+ (list
+ :program program
+ :args args
+ :exit-code exit-code
+ :stdout stdout
+ :stderr stderr
+ :default-directory default-directory
+ :process-environment process-environment))
+ (list exit-code stdout stderr))))
+
+;;; Utility Functions
+
+(defun rustic-racer-slurp (file)
+ "Return the contents of FILE as a string."
+ (with-temp-buffer
+ (insert-file-contents-literally file)
+ (buffer-string)))
+
+(defun rustic-racer-read-rust-string (string)
+ "Convert STRING, a rust string literal, to an elisp string."
+ (when string
+ (->> string
+ ;; Remove outer double quotes.
+ (s-chop-prefix "\"")
+ (s-chop-suffix "\"")
+ ;; Replace escaped characters.
+ (s-replace "\\n" "\n")
+ (s-replace "\\\"" "\"")
+ (s-replace "\\'" "'")
+ (s-replace "\\;" ";"))))
+
+(defun rustic-racer-url-p (target)
+ "Return t if TARGET looks like a fully qualified URL."
+ (not (null
+ (string-match-p (rx bol "http" (? "s") "://") target))))
+
+(defun rustic-racer-propertize-links (markdown)
+ "Propertize links in MARKDOWN."
+ (replace-regexp-in-string
+ ;; Text of the form [foo](http://example.com)
+ (rx "[" (group (+? (not (any "]")))) "](" (group (+? anything)) ")")
+ ;; For every match:
+ (lambda (whole-match)
+ ;; Extract link and target.
+ (let ((link-text (match-string 1 whole-match))
+ (link-target (match-string 2 whole-match)))
+ ;; If it's a web URL, use a clickable link.
+ (if (rustic-racer-url-p link-target)
+ (rustic-racer-url-button link-text link-target)
+ ;; Otherwise, just discard the target.
+ link-text)))
+ markdown))
+
+(defun rustic-racer-propertize-all-inline-code (markdown)
+ "Given a single line MARKDOWN, replace all instances of `foo` or
+\[`foo`\] with a propertized string."
+ (let ((highlight-group
+ (lambda (whole-match)
+ (rustic-racer-syntax-highlight (match-string 1 whole-match)))))
+ (->> markdown
+ (replace-regexp-in-string
+ (rx "[`" (group (+? anything)) "`]")
+ highlight-group)
+ (replace-regexp-in-string
+ (rx "`" (group (+? anything)) "`")
+ highlight-group))))
+
+(defun rustic-racer-indent-block (str)
+ "Indent every line in STR."
+ (s-join "\n" (--map (concat " " it) (s-lines str))))
+
+(defun rustic-racer-trim-newlines (str)
+ "Remove newlines from the start and end of STR."
+ (->> str
+ (s-chop-prefix "\n")
+ (s-chop-suffix "\n")))
+
+(defun rustic-racer-remove-footnote-links (str)
+ "Remove footnote links from markdown STR."
+ (->> (s-lines str)
+ (--remove (string-match-p (rx bol "[`" (+? anything) "`]: ") it))
+ (s-join "\n")
+ ;; Collapse consecutive blank lines caused by removing footnotes.
+ (s-replace "\n\n\n" "\n\n")))
+
+(defun rustic-racer-docstring-sections (docstring)
+ "Split DOCSTRING into text, code and heading sections."
+ (let* ((sections nil)
+ (current-section-lines nil)
+ (section-type :text)
+ ;; Helper function.
+ (finish-current-section
+ (lambda ()
+ (when current-section-lines
+ (let ((current-section
+ (s-join "\n" (nreverse current-section-lines))))
+ (unless (s-blank? current-section)
+ (push (list section-type current-section) sections))
+ (setq current-section-lines nil))))))
+ (dolist (line (s-lines docstring))
+ (cond
+ ;; If this is a closing ```
+ ((and (s-starts-with-p "```" line) (eq section-type :code))
+ (push line current-section-lines)
+ (funcall finish-current-section)
+ (setq section-type :text))
+ ;; If this is an opening ```
+ ((s-starts-with-p "```" line)
+ (funcall finish-current-section)
+ (push line current-section-lines)
+ (setq section-type :code))
+ ;; Headings
+ ((and (not (eq section-type :code)) (s-starts-with-p "# " line))
+ (funcall finish-current-section)
+ (push (list :heading line) sections))
+ ;; Normal text.
+ (t
+ (push line current-section-lines))))
+ (funcall finish-current-section)
+ (nreverse sections)))
+
+(defun rustic-racer-clean-code-section (section)
+ "Given a SECTION, a markdown code block, remove
+fenced code delimiters and code annotations."
+ (->> (s-lines section)
+ (-drop 1)
+ (-drop-last 1)
+ ;; Ignore annotations like # #[allow(dead_code)]
+ (--remove (s-starts-with-p "# " it))
+ (s-join "\n")))
+
+(defun rustic-racer-propertize-docstring (docstring)
+ "Replace markdown syntax in DOCSTRING with text properties."
+ (let* ((sections (rustic-racer-docstring-sections docstring))
+ (propertized-sections
+ (--map (-let [(section-type section) it]
+ ;; Remove trailing newlines, so we can ensure we
+ ;; have consistent blank lines between sections.
+ (rustic-racer-trim-newlines
+ (pcase section-type
+ (:text
+ (rustic-racer-propertize-all-inline-code
+ (rustic-racer-propertize-links
+ (rustic-racer-remove-footnote-links
+ section))))
+ (:code
+ (rustic-racer-indent-block
+ (rustic-racer-syntax-highlight
+ (rustic-racer-clean-code-section section))))
+ (:heading
+ (rustic-racer-header
+ (s-chop-prefix "# " section))))))
+ sections)))
+ (s-join "\n\n" propertized-sections)))
+
+(defun rustic-racer-find-file (path line column)
+ "Open PATH and move point to LINE and COLUMN."
+ (find-file path)
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (forward-char column))
+
+(defun rustic-racer-kind-description (raw-kind)
+ "Human friendly description of a rust kind.
+For example, 'EnumKind' -> 'an enum kind'."
+ (let* ((parts (s-split-words raw-kind))
+ (description (s-join " " (--map (downcase it) parts)))
+ (a (if (string-match-p (rx bos (or "a" "e" "i" "o" "u")) description)
+ "an" "a")))
+ (format "%s %s" a description)))
+
+(defun rustic-racer-current-column ()
+ "Get the current column based on underlying character representation."
+ (length (buffer-substring-no-properties
+ (line-beginning-position) (point))))
+
+(defun rustic-racer-syntax-highlight (str)
+ "Apply font-lock properties to a string STR of Rust code."
+ (let (result)
+ ;; Load all of STR in a rustic-mode buffer, and use its
+ ;; highlighting.
+ (with-temp-buffer
+ (insert str)
+ (delay-mode-hooks (rustic-mode))
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ (with-no-warnings
+ (font-lock-fontify-buffer)))
+ (setq result (buffer-string)))
+ (when (and
+ ;; If we haven't applied any properties yet,
+ (null (text-properties-at 0 result))
+ ;; and if it's a standalone symbol, then assume it's a
+ ;; variable.
+ (string-match-p (rx bos (+ (any lower "_")) eos) str))
+ (setq result (propertize str 'face 'font-lock-variable-name-face)))
+ result))
+
+(defun rustic-racer-split-parts (raw-output)
+ "Given RAW-OUTPUT from racer, split on semicolons and doublequotes.
+Unescape strings as necessary."
+ (let ((parts nil)
+ (current "")
+ (i 0))
+ (while (< i (length raw-output))
+ (let ((char (elt raw-output i))
+ (prev-char (and (> i 0) (elt raw-output (1- i)))))
+ (cond
+ ;; A semicolon that wasn't escaped, start a new part.
+ ((and (equal char ?\;) (not (equal prev-char ?\\)))
+ (push current parts)
+ (setq current ""))
+ (t
+ (setq current (concat current (string char))))))
+ (setq i (1+ i)))
+ (push current parts)
+ (mapcar #'rustic-racer-read-rust-string (nreverse parts))))
+
+(defun rustic-racer-split-snippet-match (line)
+ "Given LINE, a string \"MATCH ...\" from complete-with-snippet,
+split it into its constituent parts."
+ (let* ((match-parts (rustic-racer-split-parts line))
+ (docstring (nth 7 match-parts)))
+ (when (and match-parts (equal (length match-parts) 8))
+ (list :name (s-chop-prefix "MATCH " (nth 0 match-parts))
+ :line (string-to-number (nth 2 match-parts))
+ :column (string-to-number (nth 3 match-parts))
+ :path (nth 4 match-parts)
+ ;; Struct or Function:
+ :kind (nth 5 match-parts)
+ :signature (nth 6 match-parts)
+ :docstring (if (> (length docstring) 0) docstring nil)))))
+
+;;; Interactive
+
+;;;###autoload
+(defun rustic-racer-describe ()
+ "Show a *Racer Help* buffer for the function or type at point."
+ (interactive)
+ (let ((buf (rustic-racer-doc (thing-at-point 'symbol))))
+ (if buf
+ (pop-to-buffer buf)
+ (user-error "No function or type found at point"))))
+
+;;; _
+(provide 'rustic-racer)
+;;; rustic-racer.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-rustfix.el b/emacs.d/elpa/rustic-20210609.1900/rustic-rustfix.el
new file mode 100644
index 0000000..2e44e8f
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-rustfix.el
@@ -0,0 +1,33 @@
+;;; rustic-rustfix.el --- Support for rustfix -*- lexical-binding:t -*-
+;;; Commentary:
+
+;; This library implements support for `rustfix', a tool that applies
+;; the suggestions made by `rustc'.
+
+;;; Code:
+
+(require 'rustic-cargo)
+
+(defvar rustic-rustfix-process-name "rustic-rustfix-process"
+ "Process name for rustfix processes.")
+
+(defvar rustic-rustfix-buffer-name "*cargo-rustfix*"
+ "Buffer name for rustfix buffers.")
+
+(define-derived-mode rustic-rustfix-mode rustic-compilation-mode "rustfix"
+ :group 'rustic)
+
+;;;###autoload
+(defun rustic-rustfix ()
+ "Run 'cargo fix'."
+ (interactive)
+ (let* ((command (list rustic-cargo-bin "fix" "--allow-dirty"))
+ (err-buf rustic-rustfix-buffer-name)
+ (proc rustic-rustfix-process-name)
+ (mode 'rustic-rustfix-mode))
+ (rustic-compilation-process-live)
+ (rustic-compilation-start command (list :buffer err-buf :process proc :mode mode))))
+
+;;; _
+(provide 'rustic-rustfix)
+;;; rustic-rustfix.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic-rustfmt.el b/emacs.d/elpa/rustic-20210609.1900/rustic-rustfmt.el
new file mode 100644
index 0000000..921cfdd
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic-rustfmt.el
@@ -0,0 +1,301 @@
+;;; rustic-rustfmt.el --- Support for rustfmt -*- lexical-binding:t -*-
+;;; Commentary:
+
+;; This library implements support for `rustfmt', a tool that formats
+;; Rust code according to style guidelines.
+
+;;; Code:
+
+(require 'rustic-cargo)
+
+(declare-function project-root "project")
+
+;;; Options
+
+(defcustom rustic-rustfmt-bin "rustfmt"
+ "Path to rustfmt executable."
+ :type 'string
+ :group 'rustic)
+
+(defcustom rustic-rustfmt-config-alist nil
+ "An alist of (KEY . VAL) pairs that are passed to rustfmt.
+
+KEY is a symbol that corresponds to a config value of rustfmt.
+VALUE is a string, an integer or a boolean."
+ :type '(alist :key-type symbol
+ :value-type (choice string integer boolean))
+ :group 'rustic)
+
+(defcustom rustic-format-trigger nil
+ "Format future rust buffers before saving using rustfmt."
+ :type '(choice (const :tag "Format buffer before saving." on-save)
+ (const :tag "Run 'cargo fmt' before compilation." on-compile)
+ (const :tag "Don't format automatically." nil))
+ :group 'rustic)
+
+(defcustom rustic-format-display-method 'pop-to-buffer
+ "Default function used for displaying rustfmt buffer."
+ :type 'function
+ :group 'rustic)
+
+;;; _
+
+(defvar rustic-format-process-name "rustic-rustfmt-process"
+ "Process name for rustfmt processes.")
+
+(defvar rustic-format-buffer-name "*rustfmt*"
+ "Buffer name for rustfmt process buffers.")
+
+(defvar rustic-save-pos nil
+ "Marker, holding location of the cursor's position before
+running rustfmt.")
+
+(defun rustic-format-start-process (sentinel &rest args)
+ "Run rustfmt with ARGS.
+
+:buffer BUFFER -- BUFFER is the buffer that is being formatted.
+
+:stdin STRING -- STRING will be written to the standard input of rustfmt.
+When `:files' is non-nil, STRING will be ignored by rustfmt.
+
+:files FILES -- FILES is a string or list of strings that
+specify the input file or files to rustfmt.
+
+:command COMMAND -- COMMAND is a string or a list of strings.
+When COMMAND is non-nil, it replaces the default command.
+When COMMAND is a string, it is the program file name.
+When COMMAND is a list, it's `car' is the program file name
+and it's `cdr' is a list of arguments."
+ (let* ((err-buf (get-buffer-create rustic-format-buffer-name))
+ (inhibit-read-only t)
+ (dir (rustic-buffer-workspace))
+ (buffer (plist-get args :buffer))
+ (string (plist-get args :stdin))
+ (files (plist-get args :files))
+ (files (if (listp files) files (list files)))
+ (command (or (plist-get args :command)
+ (cons rustic-rustfmt-bin (rustic-compute-rustfmt-args))))
+ (command (if (listp command) command (list command))))
+ (setq rustic-save-pos (set-marker (make-marker) (point) (current-buffer)))
+ (rustic-compilation-setup-buffer err-buf dir 'rustic-format-mode t)
+ (--each files
+ (unless (file-exists-p it)
+ (error (format "File %s does not exist." it))))
+ (with-current-buffer err-buf
+ (let ((proc (rustic-make-process :name rustic-format-process-name
+ :buffer err-buf
+ :command `(,@command "--" ,@files)
+ :filter #'rustic-compilation-filter
+ :sentinel sentinel)))
+ (setq next-error-last-buffer buffer)
+ (when string
+ (while (not (process-live-p proc))
+ (sleep-for 0.01))
+ (process-send-string proc (concat string "\n"))
+ (process-send-eof proc))
+ proc))))
+
+(defun rustic-compute-rustfmt-args ()
+ "Compute the arguments to rustfmt from `rustic-rustfmt-config-alist'."
+ (let (args)
+ (cl-dolist (elem rustic-rustfmt-config-alist args)
+ (cl-destructuring-bind (key . val) elem
+ (push (format "%s=%s" key (if (booleanp val) (if val "true" "false") val)) args)
+ (push "--config" args)))))
+
+(defun rustic-format-sentinel (proc output)
+ "Sentinel for rustfmt processes when using stdin."
+ (ignore-errors
+ (let ((proc-buffer (process-buffer proc))
+ (inhibit-read-only t))
+ (with-current-buffer proc-buffer
+ (if (string-match-p "^finished" output)
+ (let ((file-buffer next-error-last-buffer)
+ ;; replace-buffer-contents was in emacs 26.1, but it
+ ;; was broken for non-ASCII strings, so we need 26.2.
+ (use-replace (version<= "26.2" emacs-version)))
+ (unless use-replace
+ (copy-to-buffer file-buffer (point-min) (point-max)))
+ (with-current-buffer file-buffer
+ (if use-replace
+ (replace-buffer-contents proc-buffer))
+ (goto-char rustic-save-pos))
+ (kill-buffer proc-buffer)
+ (message "Formatted buffer with rustfmt."))
+ (goto-char (point-min))
+ (when-let ((file (buffer-file-name next-error-last-buffer)))
+ (save-excursion
+ (save-match-data
+ (when (search-forward "<stdin>" nil t)
+ (replace-match file)))))
+ (with-current-buffer next-error-last-buffer
+ (goto-char rustic-save-pos))
+ (funcall rustic-format-display-method proc-buffer)
+ (message "Rustfmt error."))))))
+
+(defun rustic-format-file-sentinel (proc output)
+ "Sentinel for rustfmt processes when formatting a file."
+ (ignore-errors
+ (let ((proc-buffer (process-buffer proc)))
+ (with-current-buffer proc-buffer
+ (if (string-match-p "^finished" output)
+ (with-current-buffer next-error-last-buffer
+ (revert-buffer t t))
+ (sit-for 0.1)
+ (with-current-buffer next-error-last-buffer
+ (goto-char rustic-save-pos))
+ (goto-char (point-min))
+ (funcall rustic-format-display-method proc-buffer)
+ (message "Rustfmt error."))))))
+
+(define-derived-mode rustic-format-mode rustic-compilation-mode "rustfmt"
+ :group 'rustic)
+
+(define-derived-mode rustic-cargo-fmt-mode rustic-compilation-mode "cargo-fmt"
+ :group 'rustic)
+
+;;;###autoload
+(defun rustic-cargo-fmt ()
+ "Use rustfmt via cargo."
+ (interactive)
+ (let ((command (list rustic-cargo-bin "fmt"))
+ (buffer rustic-format-buffer-name)
+ (proc rustic-format-process-name)
+ (mode 'rustic-cargo-fmt-mode))
+ (rustic-compilation-process-live)
+ (rustic-compilation command
+ (list
+ :no-display t
+ :buffer buffer
+ :process proc
+ :mode mode
+ :sentinel #'rustic-cargo-fmt-sentinel))))
+
+(defun rustic-cargo-fmt-sentinel (proc output)
+ "Sentinel for formatting with `rustic-cargo-fmt'."
+ (let ((proc-buffer (process-buffer proc))
+ (inhibit-read-only t))
+ (with-current-buffer proc-buffer
+ (if (not (string-match-p "^finished" output))
+ (funcall rustic-compile-display-method proc-buffer)
+ (when (fboundp rustic-list-project-buffers-function)
+ (let ((buffers (cl-remove-if-not
+ #'buffer-file-name
+ (funcall rustic-list-project-buffers-function))))
+ (dolist (b buffers)
+ (with-current-buffer b
+ (revert-buffer t t)))))
+ (kill-buffer proc-buffer)
+ (message "Workspace formatted with cargo-fmt.")))))
+
+;;;###autoload
+(defun rustic-format-buffer ()
+ "Format the current buffer using rustfmt.
+
+Provide optional argument NO-STDIN for `rustic-before-save-hook' since there
+were issues when using stdin for formatting."
+ (interactive)
+ (unless (or (eq major-mode 'rustic-mode)
+ (eq major-mode 'rustic-macro-expansion-mode))
+ (error "Not a rustic-mode buffer."))
+ (rustic-compilation-process-live t)
+ (rustic-format-start-process 'rustic-format-sentinel
+ :buffer (current-buffer)
+ :stdin (buffer-string)))
+
+;;;###autoload
+(defun rustic-format-file (&optional file)
+ "Unlike `rustic-format-buffer' format file directly and revert the buffer."
+ (interactive "P")
+ (let* ((buf (current-buffer))
+ (file (or (if file (read-from-minibuffer "Format file: ") nil)
+ (buffer-file-name buf)
+ (read-from-minibuffer "Format file: ")))
+ (string (buffer-string)))
+ (write-region string nil file nil 0)
+ (let ((proc (rustic-format-start-process 'rustic-format-file-sentinel
+ :buffer buf
+ :files file)))
+ (while (eq (process-status proc) 'run)
+ (sit-for 0.05)))))
+
+(defun rustic-project-buffer-list ()
+ "Return a list of the buffers belonging to the current project.
+This is basically a wrapper around `project--buffer-list'."
+ (when-let ((pr (project-current)))
+ (if (fboundp 'project--buffer-list)
+ (project--buffer-list pr)
+ ;; Like the above function but for releases before Emacs 28.
+ (let ((root (project-root pr))
+ bufs)
+ (dolist (buf (buffer-list))
+ (let ((filename (or (buffer-file-name buf)
+ (buffer-local-value 'default-directory buf))))
+ (when (and filename (file-in-directory-p filename root))
+ (push buf bufs))))
+ (nreverse bufs)))))
+
+;;; Hooks
+
+(defun rustic-maybe-format-before-compilation ()
+ (if (eq rustic-format-trigger 'on-compile)
+ (let ((proc (rustic-cargo-fmt)))
+ (while (eq (process-status proc) 'run)
+ (sit-for 0.1))
+ (and (not (zerop (process-exit-status proc)))
+ (funcall rustic-compile-display-method (process-buffer proc))
+ t))
+ t))
+
+(add-hook 'rustic-before-compilation-hook
+ #'rustic-maybe-format-before-compilation)
+
+(defun rustic-before-save-hook ()
+ "Don't throw error if rustfmt isn't installed, as it makes saving impossible."
+ (when (and (rustic-format-on-save-p)
+ (not (rustic-compilation-process-live t)))
+ (condition-case nil
+ (progn
+ (rustic-format-file)
+ (sit-for 0.1))
+ (error nil))))
+
+(defun rustic-after-save-hook ()
+ "Check if rustfmt is installed after saving the file."
+ (when (rustic-format-on-save-p)
+ (unless (executable-find rustic-rustfmt-bin)
+ (error "Could not locate executable \"%s\"" rustic-rustfmt-bin))))
+
+(defun rustic-maybe-format-after-save (buffer)
+ (when (rustic-format-on-save-p)
+ (let* ((file (buffer-file-name buffer))
+ (proc (rustic-format-start-process
+ 'rustic-format-file-sentinel
+ :buffer buffer
+ :files file)))
+ (while (eq (process-status proc) 'run)
+ (sit-for 0.1)))))
+
+(defvar rustic-format-on-save nil
+ "Format rust buffers before saving using rustfmt.")
+
+(make-obsolete 'rustic-format-on-save 'rustic-format-trigger "Rustic 0.19")
+
+(defun rustic-format-on-save-p ()
+ "Return non-nil if formatting should happen when saving.
+See option `rustic-format-trigger'. For backward compatibility,
+if obsolete `rustic-format-on-save' is non-nil, then also return
+non-nil."
+ (or rustic-format-on-save (eq rustic-format-trigger 'on-save)))
+
+(defun rustic-save-some-buffers-advice (orig-fun &rest args)
+ (let ((rustic-format-trigger nil)
+ (rustic-format-on-save nil))
+ (apply orig-fun args)))
+
+(advice-add 'save-some-buffers :around
+ #'rustic-save-some-buffers-advice)
+
+;;; _
+(provide 'rustic-rustfmt)
+;;; rustic-rustfmt.el ends here
diff --git a/emacs.d/elpa/rustic-20210609.1900/rustic.el b/emacs.d/elpa/rustic-20210609.1900/rustic.el
new file mode 100644
index 0000000..e85ee72
--- /dev/null
+++ b/emacs.d/elpa/rustic-20210609.1900/rustic.el
@@ -0,0 +1,1253 @@
+;;; rustic.el --- Rust development environment -*-lexical-binding: t-*-
+
+;; Version: 1.3
+;; Author: Mozilla
+;;
+;; Keywords: languages
+;; Package-Requires: ((emacs "26.1") (dash "2.13.0") (f "0.18.2") (let-alist "1.0.4") (markdown-mode "2.3") (project "0.3.0") (s "1.10.0") (seq "2.3") (spinner "1.7.3") (xterm-color "1.6"))
+
+;; This file is distributed under the terms of both the MIT license and the
+;; Apache License (version 2.0).
+
+;;; Commentary:
+
+;; This package is a fork of rust-mode.
+;;
+;; Differences with rust-mode:
+;;
+;; - rust-analyzer configuration
+;; - flycheck integration
+;; - cargo popup
+;; - multiline error parsing
+;; - translation of ANSI control sequences through xterm-color
+;; - async org babel
+;; - custom compilation process
+;; - rustfmt errors in a rust compilation mode
+;; - automatic RLS configuration with eglot or lsp-mode
+;; - cask for testing
+;; - requires emacs 26
+;; - etc.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'pcase)
+(require 'seq)
+(require 'subr-x)
+
+(require 'dash)
+
+(eval-when-compile (require 'rx))
+
+(defvar electric-pair-inhibit-predicate)
+(defvar electric-pair-skip-self)
+(defvar electric-indent-chars)
+
+;;; Customization
+
+(defgroup rustic nil
+ "Support for Rust code."
+ :link '(url-link "https://www.rustic-lang.org/")
+ :group 'languages)
+
+(defcustom rustic-indent-offset 4
+ "Indent Rust code by this number of spaces."
+ :type 'integer
+ :group 'rustic
+ :safe #'integerp)
+
+(defcustom rustic-indent-method-chain nil
+ "Indent Rust method chains, aligned by the `.' operators."
+ :type 'boolean
+ :group 'rustic
+ :safe #'booleanp)
+
+(defcustom rustic-indent-where-clause nil
+ "Indent lines starting with the `where' keyword following a function or trait.
+When nil, `where' will be aligned with `fn' or `trait'."
+ :type 'boolean
+ :group 'rustic
+ :safe #'booleanp)
+
+(defcustom rustic-match-angle-brackets t
+ "Whether to enable angle bracket (`<' and `>') matching where appropriate."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'rustic)
+
+(defcustom rustic-indent-return-type-to-arguments t
+ "Indent a line starting with the `->' (RArrow) following a function, aligning
+to the function arguments. When nil, `->' will be indented one level."
+ :type 'boolean
+ :group 'rustic
+ :safe #'booleanp)
+
+;;; Faces
+
+(define-obsolete-face-alias 'rustic-unsafe-face
+ 'rustic-unsafe "1.2")
+(define-obsolete-face-alias 'rustic-question-mark-face
+ 'rustic-question-mark "1.2")
+(define-obsolete-face-alias 'rustic-builtin-formatting-macro-face
+ 'rustic-builtin-formatting-macro "1.2")
+(define-obsolete-face-alias 'rustic-string-interpolation-face
+ 'rustic-string-interpolation "1.2")
+
+(defface rustic-unsafe
+ '((t :inherit font-lock-warning-face))
+ "Face for the `unsafe' keyword."
+ :group 'rustic)
+
+(defface rustic-question-mark
+ '((t :weight bold :inherit font-lock-builtin-face))
+ "Face for the question mark operator."
+ :group 'rustic)
+
+(defface rustic-builtin-formatting-macro
+ '((t :inherit font-lock-builtin-face))
+ "Face for builtin formatting macros (print! &c.)."
+ :group 'rustic)
+
+(defface rustic-string-interpolation
+ '((t :slant italic :inherit font-lock-string-face))
+ "Face for interpolating braces in builtin formatting macro strings."
+ :group 'rustic)
+
+;;; Workspace
+
+(defvar-local rustic--buffer-workspace nil
+ "Use function `rustic-buffer-workspace' instead.")
+
+(defun rustic-buffer-workspace (&optional nodefault)
+ "Return the Rust workspace for the current buffer.
+This is the directory containing the file \"Cargo.lock\". When
+called outside a Rust project, then return `default-directory',
+or if NODEFAULT is non-nil, then fall back to returning nil."
+ (or rustic--buffer-workspace
+ (let ((dir (locate-dominating-file default-directory "Cargo.toml")))
+ (when dir
+ (setq dir (expand-file-name dir)))
+ (setq rustic--buffer-workspace dir)
+ (or dir
+ (and (not nodefault)
+ default-directory)))))
+
+;;; Syntax
+
+(defconst rustic-re-ident "[[:word:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*")
+(defconst rustic-re-lc-ident "[[:lower:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*")
+(defconst rustic-re-uc-ident "[[:upper:]][[:word:][:multibyte:]_[:digit:]]*")
+(defconst rustic-re-vis "pub")
+(defconst rustic-re-unsafe "unsafe")
+(defconst rustic-re-extern "extern")
+(defconst rustic-re-generic
+ (concat "<[[:space:]]*'" rustic-re-ident "[[:space:]]*>"))
+(defconst rustic-re-union
+ (rx-to-string
+ `(seq
+ (or space line-start)
+ (group symbol-start "union" symbol-end)
+ (+ space) (regexp ,rustic-re-ident))))
+
+(defun rustic-re-shy (inner) (concat "\\(?:" inner "\\)"))
+(defun rustic-re-grab (inner) (concat "\\(" inner "\\)"))
+(defun rustic-re-item-def (itype)
+ (concat (rustic-re-word itype)
+ (rustic-re-shy rustic-re-generic) "?"
+ "[[:space:]]+" (rustic-re-grab rustic-re-ident)))
+(defun rustic-re-word (inner) (concat "\\<" inner "\\>"))
+
+(defun rustic-re-item-def-imenu (itype)
+ (concat "^[[:space:]]*"
+ (rustic-re-shy (concat (rustic-re-word rustic-re-vis) "[[:space:]]+")) "?"
+ (rustic-re-shy (concat (rustic-re-word "default") "[[:space:]]+")) "?"
+ (rustic-re-shy (concat (rustic-re-word rustic-re-unsafe) "[[:space:]]+")) "?"
+ (rustic-re-shy (concat (rustic-re-word rustic-re-extern) "[[:space:]]+"
+ (rustic-re-shy "\"[^\"]+\"[[:space:]]+") "?")) "?"
+ (rustic-re-item-def itype)))
+
+(defvar rustic-imenu-generic-expression
+ (append (mapcar #'(lambda (x)
+ (list (capitalize x) (rustic-re-item-def-imenu x) 1))
+ '("async fn" "enum" "struct" "union" "type" "mod" "fn" "trait" "impl"))
+ `(("Macro" ,(rustic-re-item-def-imenu "macro_rules!") 1)))
+ "Value for `imenu-generic-expression' in Rust mode.
+
+Create a hierarchical index of the item definitions in a Rust file.
+
+Imenu will show all the enums, structs, etc. in their own subheading.
+Use idomenu (imenu with `ido-mode') for best mileage.")
+
+(defvar rustic-mode-syntax-table
+ (let ((table (make-syntax-table)))
+
+ ;; Operators
+ (dolist (i '(?+ ?- ?* ?/ ?% ?& ?| ?^ ?! ?< ?> ?~ ?@))
+ (modify-syntax-entry i "." table))
+
+ ;; Strings
+ (modify-syntax-entry ?\" "\"" table)
+ (modify-syntax-entry ?\\ "\\" table)
+
+ ;; Angle brackets. We suppress this with syntactic propertization
+ ;; when needed
+ (modify-syntax-entry ?< "(>" table)
+ (modify-syntax-entry ?> ")<" table)
+
+ ;; Comments
+ (modify-syntax-entry ?/ ". 124b" table)
+ (modify-syntax-entry ?* ". 23n" table)
+ (modify-syntax-entry ?\n "> b" table)
+ (modify-syntax-entry ?\^m "> b" table)
+
+ table)
+ "Syntax definitions and helpers.")
+
+;;; Mode
+
+(defvar rustic-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-c C-p") 'rustic-popup)
+
+ (define-key map (kbd "C-c C-c C-u") 'rustic-compile)
+ (define-key map (kbd "C-c C-c C-i") 'rustic-recompile)
+ (define-key map (kbd "C-c C-c C-b") 'rustic-cargo-build)
+ (define-key map (kbd "C-c C-c C-k") 'rustic-cargo-check)
+ (define-key map (kbd "C-c C-c C-r") 'rustic-cargo-run)
+ (define-key map (kbd "C-c C-c C-f") 'rustic-cargo-fmt)
+ (define-key map (kbd "C-c C-c C-t") 'rustic-cargo-test)
+ (define-key map (kbd "C-c C-c C-c") 'rustic-cargo-current-test)
+ (define-key map (kbd "C-c C-c C-l") 'rustic-cargo-clippy)
+ (define-key map (kbd "C-c C-c C-o") 'rustic-format-buffer)
+
+ (define-key map (kbd "C-c C-c C-d") 'rustic-racer-describe)
+ (define-key map (kbd "C-c C-c C-,") 'rustic-docstring-dwim)
+ (define-key map (kbd "C-c C-c C-n") 'rustic-cargo-outdated)
+ map)
+ "Keymap for Rust major mode.")
+
+;;;###autoload
+(define-derived-mode rustic-mode prog-mode "Rustic"
+ "Major mode for Rust code.
+
+\\{rustic-mode-map}"
+ :group 'rustic
+ :syntax-table rustic-mode-syntax-table
+
+ ;; Syntax
+ (setq-local syntax-propertize-function #'rustic-syntax-propertize)
+
+ ;; Indentation
+ (setq-local indent-line-function 'rustic-indent-line)
+
+ ;; Fonts
+ (setq-local font-lock-defaults
+ '(rustic-font-lock-keywords
+ nil nil nil nil
+ (font-lock-syntactic-face-function
+ . rustic-syntactic-face-function)))
+
+ ;; Misc
+ (setq-local comment-start "// ")
+ (setq-local comment-end "")
+ (setq-local open-paren-in-column-0-is-defun-start nil)
+
+ ;; Auto indent on }
+ (setq-local electric-indent-chars
+ (cons ?} (and (boundp 'electric-indent-chars)
+ electric-indent-chars)))
+
+ ;; Allow paragraph fills for comments
+ (setq-local comment-start-skip "\\(?://[/!]*\\|/\\*[*!]?\\)[[:space:]]*")
+ (setq-local paragraph-start
+ (concat "[[:space:]]*\\(?:"
+ comment-start-skip
+ "\\|\\*/?[[:space:]]*\\|\\)$"))
+ (setq-local paragraph-separate paragraph-start)
+ (setq-local normal-auto-fill-function 'rustic-do-auto-fill)
+ (setq-local fill-paragraph-function 'rustic-fill-paragraph)
+ (setq-local fill-forward-paragraph-function 'rustic-fill-forward-paragraph)
+ (setq-local adaptive-fill-function 'rustic-find-fill-prefix)
+ (setq-local adaptive-fill-first-line-regexp "")
+ (setq-local comment-multi-line t)
+ (setq-local comment-line-break-function 'rustic-comment-indent-new-line)
+ (setq-local imenu-generic-expression rustic-imenu-generic-expression)
+ (setq-local imenu-syntax-alist '((?! . "w"))) ; For macro_rules!
+ (setq-local beginning-of-defun-function 'rustic-beginning-of-defun)
+ (setq-local end-of-defun-function 'rustic-end-of-defun)
+ (setq-local parse-sexp-lookup-properties t)
+ (setq-local electric-pair-inhibit-predicate
+ 'rustic-electric-pair-inhibit-predicate-wrap)
+ (setq-local electric-pair-skip-self 'rustic-electric-pair-skip-self-wrap)
+
+ (when (fboundp 'rustic-before-save-hook)
+ (add-hook 'before-save-hook 'rustic-before-save-hook nil t)
+ (add-hook 'after-save-hook 'rustic-after-save-hook nil t)))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.rs\\'" . rustic-mode))
+
+;; remove rust-mode from `auto-mode-alist'
+(let ((mode '("\\.rs\\'" . rust-mode)))
+ (when (member mode auto-mode-alist)
+ (setq auto-mode-alist (remove mode auto-mode-alist))))
+
+(defvar rustic-top-item-beg-re
+ (concat "\\s-*\\(?:priv\\|pub\\)?\\s-*"
+ (regexp-opt
+ '("enum" "struct" "union" "type" "mod" "use" "fn" "static" "impl"
+ "extern" "trait" "async"))
+ "\\_>")
+ "Start of a Rust item.")
+
+(defconst rustic-re-type-or-constructor
+ (rx symbol-start
+ (group upper (0+ (any word nonascii digit "_")))
+ symbol-end))
+
+(defconst rustic-keywords
+ '("as" "async" "await"
+ "box" "break"
+ "const" "continue" "crate"
+ "do" "dyn"
+ "else" "enum" "extern" "existential"
+ "false" "fn" "for"
+ "if" "impl" "in"
+ "let" "loop"
+ "match" "mod" "move" "mut"
+ "priv" "pub"
+ "ref" "return"
+ "self" "static" "struct" "super"
+ "true" "trait" "type" "try"
+ "use"
+ "virtual"
+ "where" "while"
+ "yield")
+ "Font-locking definitions and helpers.")
+
+(defconst rustic-special-types
+ '("u8" "i8"
+ "u16" "i16"
+ "u32" "i32"
+ "u64" "i64"
+ "u128" "i128"
+
+ "f32" "f64"
+ "isize" "usize"
+ "bool"
+ "str" "char"))
+
+(defvar rustic-builtin-formatting-macros
+ '("eprint"
+ "eprintln"
+ "format"
+ "print"
+ "println")
+ "List of builtin Rust macros for string formatting.
+This is used by `rust-font-lock-keywords'.
+\(`write!' is handled separately).")
+
+(defvar rustic-formatting-macro-opening-re
+ "[[:space:]]*[({[][[:space:]]*"
+ "Regular expression to match the opening delimiter of a Rust formatting macro.")
+
+(defvar rustic-start-of-string-re
+ "\\(?:r#*\\)?\""
+ "Regular expression to match the start of a Rust raw string.")
+
+(defun rustic-path-font-lock-matcher (re-ident)
+ "Match occurrences of RE-IDENT followed by a double-colon.
+Examples include to match names like \"foo::\" or \"Foo::\".
+Does not match type annotations of the form \"foo::<\"."
+ `(lambda (limit)
+ (catch 'rustic-path-font-lock-matcher
+ (while t
+ (let* ((symbol-then-colons (rx-to-string '(seq (group (regexp ,re-ident)) "::")))
+ (match (re-search-forward symbol-then-colons limit t)))
+ (cond
+ ;; If we didn't find a match, there are no more occurrences
+ ;; of foo::, so return.
+ ((null match) (throw 'rustic-path-font-lock-matcher nil))
+ ;; If this isn't a type annotation foo::<, we've found a
+ ;; match, so a return it!
+ ((not (looking-at (rx (0+ space) "<")))
+ (throw 'rustic-path-font-lock-matcher match))))))))
+
+(defvar rustic-font-lock-keywords
+ (append
+ `(
+ ;; Keywords proper
+ (,(regexp-opt rustic-keywords 'symbols) . font-lock-keyword-face)
+
+ ;; Contextual keywords
+ ("\\_<\\(default\\)[[:space:]]+fn\\_>" 1 font-lock-keyword-face)
+ (,rustic-re-union 1 font-lock-keyword-face)
+
+ ;; Special types
+ (,(regexp-opt rustic-special-types 'symbols) . font-lock-type-face)
+
+ ;; The unsafe keyword
+ ("\\_<unsafe\\_>" . 'rustic-unsafe)
+
+ ;; Attributes like `#[bar(baz)]` or `#![bar(baz)]` or `#[bar = "baz"]`
+ (,(rustic-re-grab (concat "#\\!?\\[" rustic-re-ident "[^]]*\\]"))
+ 1 font-lock-preprocessor-face keep)
+
+ ;; Builtin formatting macros
+ (,(concat (rustic-re-grab (concat (regexp-opt rustic-builtin-formatting-macros) "!"))
+ rustic-formatting-macro-opening-re
+ rustic-start-of-string-re)
+ (1 'rustic-builtin-formatting-macro)
+ (rustic-string-interpolation-matcher
+ (rustic-end-of-string)
+ nil
+ (0 'rustic-string-interpolation t nil)))
+
+ ;; write! macro
+ (,(concat (rustic-re-grab "write\\(ln\\)?!")
+ rustic-formatting-macro-opening-re
+ "[[:space:]]*[^\"]+,[[:space:]]*"
+ rustic-start-of-string-re)
+ (1 'rustic-builtin-formatting-macro)
+ (rustic-string-interpolation-matcher
+ (rustic-end-of-string)
+ nil
+ (0 'rustic-string-interpolation t nil)))
+
+ ;; Syntax extension invocations like `foo!`, highlight including the !
+ (,(concat (rustic-re-grab (concat rustic-re-ident "!")) "[({[:space:][]")
+ 1 font-lock-preprocessor-face)
+
+ ;; Field names like `foo:`, highlight excluding the :
+ (,(concat (rustic-re-grab rustic-re-ident) ":[^:]") 1 font-lock-variable-name-face)
+
+ ;; CamelCase Means Type Or Constructor
+ (,rustic-re-type-or-constructor 1 font-lock-type-face)
+
+ ;; Type-inferred binding
+ (,(concat "\\_<\\(?:let\\s-+ref\\|let\\|ref\\)\\s-+\\(?:mut\\s-+\\)?"
+ (rustic-re-grab rustic-re-ident)
+ "\\_>")
+ 1 font-lock-variable-name-face)
+
+ ;; Type names like `Foo::`, highlight excluding the ::
+ (,(rustic-path-font-lock-matcher rustic-re-uc-ident) 1 font-lock-type-face)
+
+ ;; Module names like `foo::`, highlight excluding the ::
+ (,(rustic-path-font-lock-matcher rustic-re-lc-ident) 1 font-lock-constant-face)
+
+ ;; Lifetimes like `'foo`
+ (,(concat "'" (rustic-re-grab rustic-re-ident) "[^']") 1 font-lock-variable-name-face)
+
+ ;; Question mark operator
+ ("\\?" . 'rustic-question-mark)
+ )
+
+ ;; Ensure we highlight `Foo` in `struct Foo` as a type.
+ (mapcar #'(lambda (x)
+ (list (rustic-re-item-def (car x))
+ 1 (cdr x)))
+ '(("enum" . font-lock-type-face)
+ ("struct" . font-lock-type-face)
+ ("union" . font-lock-type-face)
+ ("type" . font-lock-type-face)
+ ("mod" . font-lock-constant-face)
+ ("use" . font-lock-constant-face)
+ ("fn" . font-lock-function-name-face)))))
+
+(defun rustic-end-of-string ()
+ "Skip to the end of the current string."
+ (save-excursion
+ (skip-syntax-forward "^\"|")
+ (skip-syntax-forward "\"|")
+ (point)))
+
+(defun rustic-looking-back-str (str)
+ "Return non-nil if there's a match on the text before point and STR.
+Like `looking-back' but for fixed strings rather than regexps (so
+that it's not so slow)."
+ (let ((len (length str)))
+ (and (> (point) len)
+ (equal str (buffer-substring-no-properties (- (point) len) (point))))))
+
+(defun rustic-looking-back-symbols (symbols)
+ "Return non-nil if the point is after a member of SYMBOLS.
+SYMBOLS is a list of strings that represent the respective
+symbols."
+ (save-excursion
+ (let* ((pt-orig (point))
+ (beg-of-symbol (progn (forward-thing 'symbol -1) (point)))
+ (end-of-symbol (progn (forward-thing 'symbol 1) (point))))
+ (and
+ (= end-of-symbol pt-orig)
+ (member (buffer-substring-no-properties beg-of-symbol pt-orig)
+ symbols)))))
+
+(defun rustic-looking-back-ident ()
+ "Non-nil if we are looking backwards at a valid rust identifier."
+ (let ((beg-of-symbol (save-excursion (forward-thing 'symbol -1) (point))))
+ (looking-back rustic-re-ident beg-of-symbol)))
+
+(defun rustic-looking-back-macro ()
+ "Non-nil if looking back at an ident followed by a !
+
+This is stricter than rust syntax which allows a space between
+the ident and the ! symbol. If this space is allowed, then we
+would also need a keyword check to avoid `if !(condition)` being
+seen as a macro."
+ (if (> (- (point) (point-min)) 1)
+ (save-excursion
+ (backward-char)
+ (and (= ?! (char-after))
+ (rustic-looking-back-ident)))))
+
+;;; Syntax definitions and helpers
+
+(defun rustic-paren-level () (nth 0 (syntax-ppss)))
+(defun rustic-in-str () (nth 3 (syntax-ppss)))
+(defun rustic-in-str-or-cmnt () (nth 8 (syntax-ppss)))
+(defun rustic-rewind-past-str-cmnt () (goto-char (nth 8 (syntax-ppss))))
+
+(defun rustic-rewind-irrelevant ()
+ (let ((continue t))
+ (while continue
+ (let ((starting (point)))
+ (skip-chars-backward "[:space:]\n")
+ (when (rustic-looking-back-str "*/")
+ (backward-char))
+ (when (rustic-in-str-or-cmnt)
+ (rustic-rewind-past-str-cmnt))
+ ;; Rewind until the point no longer moves
+ (setq continue (/= starting (point)))))))
+
+(defvar-local rustic-macro-scopes nil
+ "Cache for the scopes calculated by `rustic-macro-scope'.
+
+This variable can be `let' bound directly or indirectly around
+`rustic-macro-scope' as an optimization but should not be otherwise
+set.")
+
+(defun rustic-macro-scope (start end)
+ "Return the scope of macros in the buffer.
+
+The return value is a list of (START END) positions in the
+buffer.
+
+If set START and END are optimizations which limit the return
+value to scopes which are approximately with this range."
+ (save-excursion
+ ;; need to special case macro_rules which has unique syntax
+ (let ((scope nil)
+ (start (or start (point-min)))
+ (end (or end (point-max))))
+ (goto-char start)
+ ;; if there is a start move back to the previous top level,
+ ;; as any macros before that must have closed by this time.
+ (let ((top (syntax-ppss-toplevel-pos (syntax-ppss))))
+ (when top
+ (goto-char top)))
+ (while
+ (and
+ ;; The movement below may have moved us passed end, in
+ ;; which case search-forward will error
+ (< (point) end)
+ (search-forward "!" end t))
+ (let ((pt (point)))
+ (cond
+ ;; in a string or comment is boring, move straight on
+ ((rustic-in-str-or-cmnt))
+ ;; in a normal macro,
+ ((and (skip-chars-forward " \t\n\r")
+ (memq (char-after)
+ '(?\[ ?\( ?\{))
+ ;; Check that we have a macro declaration after.
+ (rustic-looking-back-macro))
+ (let ((start (point)))
+ (ignore-errors (forward-list))
+ (setq scope (cons (list start (point)) scope))))
+ ;; macro_rules, why, why, why did you not use macro syntax??
+ ((save-excursion
+ ;; yuck -- last test moves point, even if it fails
+ (goto-char (- pt 1))
+ (skip-chars-backward " \t\n\r")
+ (rustic-looking-back-str "macro_rules"))
+ (save-excursion
+ (when (re-search-forward "[[({]" nil t)
+ (backward-char)
+ (let ((start (point)))
+ (ignore-errors (forward-list))
+ (setq scope (cons (list start (point)) scope)))))))))
+ ;; Return 'empty rather than nil, to indicate a buffer with no
+ ;; macros at all.
+ (or scope 'empty))))
+
+(defun rustic-in-macro (&optional start end)
+ "Return non-nil when point is within the scope of a macro.
+
+If START and END are set, minimize the buffer analysis to
+approximately this location as an optimization.
+
+Alternatively, if `rustic-macro-scopes' is a list use the scope
+information in this variable. This last is an optimization and
+the caller is responsible for ensuring that the data in
+`rustic-macro-scopes' is up to date."
+ (when (> (rustic-paren-level) 0)
+ (let ((scopes
+ (or
+ rustic-macro-scopes
+ (rustic-macro-scope start end))))
+ ;; `rustic-macro-scope' can return the symbol `empty' if the
+ ;; buffer has no macros at all.
+ (when (listp scopes)
+ (seq-some
+ (lambda (sc)
+ (and (>= (point) (car sc))
+ (< (point) (cadr sc))))
+ scopes)))))
+
+(defun rustic-looking-at-where ()
+ "Return T when looking at the \"where\" keyword."
+ (and (looking-at-p "\\bwhere\\b")
+ (not (rustic-in-str-or-cmnt))))
+
+(defun rustic-rewind-to-where (&optional limit)
+ "Rewind the point to the closest occurrence of the \"where\" keyword.
+Return T iff a where-clause was found. Does not rewind past
+LIMIT when passed, otherwise only stops at the beginning of the
+buffer."
+ (when (re-search-backward "\\bwhere\\b" limit t)
+ (if (rustic-in-str-or-cmnt)
+ (rustic-rewind-to-where limit)
+ t)))
+
+(defconst rustic-re-pre-expression-operators "[-=!%&*/:<>[{(|.^;}]")
+
+(defconst rustic-re-special-types (regexp-opt rustic-special-types 'symbols))
+
+;;; Font-locking definitions and helpers
+
+(defun rustic-next-string-interpolation (limit)
+ "Search forward from point for next Rust interpolation marker before LIMIT.
+Set point to the end of the occurrence found, and return match beginning
+and end."
+ (catch 'match
+ (save-match-data
+ (save-excursion
+ (while (search-forward "{" limit t)
+ (if (eql (char-after (point)) ?{)
+ (forward-char)
+ (let ((start (match-beginning 0)))
+ ;; According to fmt_macros::Parser::next, an opening brace
+ ;; must be followed by an optional argument and/or format
+ ;; specifier, then a closing brace. A single closing brace
+ ;; without a corresponding unescaped opening brace is an
+ ;; error. We don't need to do anything special with
+ ;; arguments, specifiers, or errors, so we only search for
+ ;; the single closing brace.
+ (when (search-forward "}" limit t)
+ (throw 'match (list start (point)))))))))))
+
+(defun rustic-string-interpolation-matcher (limit)
+ "Match next Rust interpolation marker before LIMIT and set match data if found.
+Returns nil if not within a Rust string."
+ (when (rustic-in-str)
+ (let ((match (rustic-next-string-interpolation limit)))
+ (when match
+ (set-match-data match)
+ (goto-char (cadr match))
+ match))))
+
+(defun rustic-syntax-class-before-point ()
+ (when (> (point) 1)
+ (syntax-class (syntax-after (1- (point))))))
+
+(defun rustic-rewind-qualified-ident ()
+ (while (rustic-looking-back-ident)
+ (backward-sexp)
+ (when (save-excursion (rustic-rewind-irrelevant) (rustic-looking-back-str "::"))
+ (rustic-rewind-irrelevant)
+ (backward-char 2)
+ (rustic-rewind-irrelevant))))
+
+(defun rustic-rewind-type-param-list ()
+ (cond
+ ((and (rustic-looking-back-str ">") (equal 5 (rustic-syntax-class-before-point)))
+ (backward-sexp)
+ (rustic-rewind-irrelevant))
+
+ ;; We need to be able to back up past the Fn(args) -> RT form as well. If
+ ;; we're looking back at this, we want to end up just after "Fn".
+ ((member (char-before) '(?\] ?\) ))
+ (let* ((is-paren (rustic-looking-back-str ")"))
+ (dest (save-excursion
+ (backward-sexp)
+ (rustic-rewind-irrelevant)
+ (or
+ (when (rustic-looking-back-str "->")
+ (backward-char 2)
+ (rustic-rewind-irrelevant)
+ (when (rustic-looking-back-str ")")
+ (backward-sexp)
+ (point)))
+ (and is-paren (point))))))
+ (when dest
+ (goto-char dest))))))
+
+(defun rustic-rewind-to-decl-name ()
+ "Return the point at the beginning of the name in a declaration.
+I.e. if we are before an ident that is part of a declaration that
+can have a where clause, rewind back to just before the name of
+the subject of that where clause and return the new point.
+Otherwise return nil."
+ (let* ((ident-pos (point))
+ (newpos (save-excursion
+ (rustic-rewind-irrelevant)
+ (rustic-rewind-type-param-list)
+ (cond
+ ((rustic-looking-back-symbols
+ '("fn" "trait" "enum" "struct" "union" "impl" "type"))
+ ident-pos)
+
+ ((equal 5 (rustic-syntax-class-before-point))
+ (backward-sexp)
+ (rustic-rewind-to-decl-name))
+
+ ((looking-back "[:,'+=]" (1- (point)))
+ (backward-char)
+ (rustic-rewind-to-decl-name))
+
+ ((rustic-looking-back-str "->")
+ (backward-char 2)
+ (rustic-rewind-to-decl-name))
+
+ ((rustic-looking-back-ident)
+ (rustic-rewind-qualified-ident)
+ (rustic-rewind-to-decl-name))))))
+ (when newpos (goto-char newpos))
+ newpos))
+
+(defun rustic-is-in-expression-context (token)
+ "Return t if what comes right after the point is part of an
+expression (as opposed to starting a type) by looking at what
+comes before. Takes a symbol that roughly indicates what is
+after the point.
+
+This function is used as part of `rustic-is-lt-char-operator' as
+part of angle bracket matching, and is not intended to be used
+outside of this context."
+ (save-excursion
+ (let ((postchar (char-after)))
+ (rustic-rewind-irrelevant)
+ ;; A type alias or ascription could have a type param list. Skip backwards past it.
+ (when (member token '(ambiguous-operator open-brace))
+ (rustic-rewind-type-param-list))
+ (cond
+
+ ;; Certain keywords always introduce expressions
+ ((rustic-looking-back-symbols '("if" "while" "match" "return" "box" "in")) t)
+
+ ;; "as" introduces a type
+ ((rustic-looking-back-symbols '("as")) nil)
+
+ ;; An open angle bracket never introduces expression context WITHIN the angle brackets
+ ((and (equal token 'open-brace) (equal postchar ?<)) nil)
+
+ ;; An ident! followed by an open brace is a macro invocation. Consider
+ ;; it to be an expression.
+ ((and (equal token 'open-brace) (rustic-looking-back-macro)) t)
+
+ ;; In a brace context a "]" introduces an expression.
+ ((and (eq token 'open-brace) (rustic-looking-back-str "]")))
+
+ ;; An identifier is right after an ending paren, bracket, angle bracket
+ ;; or curly brace. It's a type if the last sexp was a type.
+ ((and (equal token 'ident) (equal 5 (rustic-syntax-class-before-point)))
+ (backward-sexp)
+ (rustic-is-in-expression-context 'open-brace))
+
+ ;; If a "for" appears without a ; or { before it, it's part of an
+ ;; "impl X for y", so the y is a type. Otherwise it's
+ ;; introducing a loop, so the y is an expression
+ ((and (equal token 'ident) (rustic-looking-back-symbols '("for")))
+ (backward-sexp)
+ (rustic-rewind-irrelevant)
+ (looking-back "[{;]" (1- (point))))
+
+ ((rustic-looking-back-ident)
+ (rustic-rewind-qualified-ident)
+ (rustic-rewind-irrelevant)
+ (cond
+ ((equal token 'open-brace)
+ ;; We now know we have:
+ ;; ident <maybe type params> [{([]
+ ;; where [{([] denotes either a {, ( or [.
+ ;; This character is bound as postchar.
+ (cond
+ ;; If postchar is a paren or square bracket, then if the
+ ;; brace is a type if the identifier is one
+ ((member postchar '(?\( ?\[ )) (rustic-is-in-expression-context 'ident))
+
+ ;; If postchar is a curly brace, the brace can only be a type if
+ ;; ident2 is the name of an enum, struct or trait being declared.
+ ;; Note that if there is a -> before the ident then the ident would
+ ;; be a type but the { is not.
+ ((equal ?{ postchar)
+ (not (and (rustic-rewind-to-decl-name)
+ (progn
+ (rustic-rewind-irrelevant)
+ (rustic-looking-back-symbols
+ '("enum" "struct" "union" "trait" "type"))))))))
+
+ ((equal token 'ambiguous-operator)
+ (cond
+ ;; An ampersand after an ident has to be an operator rather
+ ;; than a & at the beginning of a ref type
+ ((equal postchar ?&) t)
+
+ ;; A : followed by a type then an = introduces an
+ ;; expression (unless it is part of a where clause of a
+ ;; "type" declaration)
+ ((and (equal postchar ?=)
+ (looking-back "[^:]:" (- (point) 2))
+ (not (save-excursion
+ (and (rustic-rewind-to-decl-name)
+ (progn (rustic-rewind-irrelevant)
+ (rustic-looking-back-symbols '("type"))))))))
+
+ ;; "let ident =" introduces an expression--and so does "const" and "mut"
+ ((and (equal postchar ?=) (rustic-looking-back-symbols '("let" "const" "mut"))) t)
+
+ ;; As a specific special case, see if this is the = in this situation:
+ ;; enum EnumName<type params> { Ident =
+ ;; In this case, this is a c-like enum and despite Ident
+ ;; representing a type, what comes after the = is an expression
+ ((and
+ (> (rustic-paren-level) 0)
+ (save-excursion
+ (backward-up-list)
+ (rustic-rewind-irrelevant)
+ (rustic-rewind-type-param-list)
+ (and
+ (rustic-looking-back-ident)
+ (progn
+ (rustic-rewind-qualified-ident)
+ (rustic-rewind-irrelevant)
+ (rustic-looking-back-str "enum")))))
+ t)
+
+ ;; Otherwise the ambiguous operator is a type if the identifier is a type
+ ((rustic-is-in-expression-context 'ident) t)))
+
+ ((equal token 'colon)
+ (cond
+ ;; If we see a ident: not inside any braces/parens, we're at top level.
+ ;; There are no allowed expressions after colons there, just types.
+ ((<= (rustic-paren-level) 0) nil)
+
+ ;; We see ident: inside a list
+ ((looking-back "[{,]" (1- (point)))
+ (backward-up-list)
+
+ ;; If a : appears whose surrounding paren/brackets/braces are
+ ;; anything other than curly braces, it can't be a field
+ ;; initializer and must be denoting a type.
+ (when (looking-at "{")
+ (rustic-rewind-irrelevant)
+ (rustic-rewind-type-param-list)
+ (when (rustic-looking-back-ident)
+ ;; We have a context that looks like this:
+ ;; ident2 <maybe type params> { [maybe paren-balanced code ending in comma] ident1:
+ ;; the point is sitting just after ident2, and we trying to
+ ;; figure out if the colon introduces an expression or a type.
+ ;; The answer is that ident1 is a field name, and what comes
+ ;; after the colon is an expression, if ident2 is an
+ ;; expression.
+ (rustic-rewind-qualified-ident)
+ (rustic-is-in-expression-context 'ident))))
+
+ ;; Otherwise, if the ident: appeared with anything other than , or {
+ ;; before it, it can't be part of a struct initializer and therefore
+ ;; must be denoting a type.
+ (t nil)))))
+
+ ;; An operator-like character after a string is indeed an operator
+ ((and (equal token 'ambiguous-operator)
+ (member (rustic-syntax-class-before-point) '(5 7 15))) t)
+
+ ;; A colon that has something other than an identifier before it is a
+ ;; type ascription
+ ((equal token 'colon) nil)
+
+ ;; A :: introduces a type (or module, but not an expression in any case)
+ ((rustic-looking-back-str "::") nil)
+
+ ((rustic-looking-back-str ":")
+ (backward-char)
+ (rustic-is-in-expression-context 'colon))
+
+ ;; A -> introduces a type
+ ((rustic-looking-back-str "->") nil)
+
+ ;; If we are up against the beginning of a list, or after a comma inside
+ ;; of one, back up out of it and check what the list itself is
+ ((or
+ (equal 4 (rustic-syntax-class-before-point))
+ (rustic-looking-back-str ","))
+ (condition-case nil
+ (progn
+ (backward-up-list)
+ (rustic-is-in-expression-context 'open-brace))
+ (scan-error nil)))
+
+ ;; A => introduces an expression
+ ((rustic-looking-back-str "=>") t)
+
+ ;; A == introduces an expression
+ ((rustic-looking-back-str "==") t)
+
+ ;; These operators can introduce expressions or types
+ ((looking-back "[-+=!?&*]" (1- (point)))
+ (backward-char)
+ (rustic-is-in-expression-context 'ambiguous-operator))
+
+ ;; These operators always introduce expressions. (Note that if this
+ ;; regexp finds a < it must not be an angle bracket, or it'd
+ ;; have been caught in the syntax-class check above instead of this.)
+ ((looking-back rustic-re-pre-expression-operators (1- (point))) t)))))
+
+(defun rustic-is-lt-char-operator ()
+ "Return non-nil if the `<' sign just after point is an operator.
+Otherwise, if it is an opening angle bracket, then return nil."
+ (let ((case-fold-search nil))
+ (save-excursion
+ (rustic-rewind-irrelevant)
+ ;; We are now just after the character syntactically before the <.
+ (cond
+
+ ;; If we are looking back at a < that is not an angle bracket (but not
+ ;; two of them) then this is the second < in a bit shift operator
+ ((and (rustic-looking-back-str "<")
+ (not (equal 4 (rustic-syntax-class-before-point)))
+ (not (rustic-looking-back-str "<<"))))
+
+ ;; On the other hand, if we are after a closing paren/brace/bracket it
+ ;; can only be an operator, not an angle bracket. Likewise, if we are
+ ;; after a string it's an operator. (The string case could actually be
+ ;; valid in rust for character literals.)
+ ((member (rustic-syntax-class-before-point) '(5 7 15)) t)
+
+ ;; If we are looking back at an operator, we know that we are at
+ ;; the beginning of an expression, and thus it has to be an angle
+ ;; bracket (starting a "<Type as Trait>::" construct.)
+ ((looking-back rustic-re-pre-expression-operators (1- (point))) nil)
+
+ ;; If we are looking back at a keyword, it's an angle bracket
+ ;; unless that keyword is "self", "true" or "false"
+ ((rustic-looking-back-symbols rustic-keywords)
+ (rustic-looking-back-symbols '("self" "true" "false")))
+
+ ((rustic-looking-back-str "?")
+ (rustic-is-in-expression-context 'ambiguous-operator))
+
+ ;; If we're looking back at an identifier, this depends on whether
+ ;; the identifier is part of an expression or a type
+ ((rustic-looking-back-ident)
+ (backward-sexp)
+ (or
+ ;; The special types can't take type param lists, so a < after one is
+ ;; always an operator
+ (looking-at rustic-re-special-types)
+
+ (rustic-is-in-expression-context 'ident)))
+
+ ;; Otherwise, assume it's an angle bracket
+ ))))
+
+(defun rustic-electric-pair-inhibit-predicate-wrap (char)
+ "Prevent \"matching\" with a `>' when CHAR is the less-than operator.
+This wraps the default defined by `electric-pair-inhibit-predicate'."
+ (or
+ (when (= ?< char)
+ (save-excursion
+ (backward-char)
+ (rustic-is-lt-char-operator)))
+ (funcall (default-value 'electric-pair-inhibit-predicate) char)))
+
+(defun rustic-electric-pair-skip-self-wrap (char)
+ "Skip CHAR instead of inserting a second closing character.
+This wraps the default defined by `electric-pair-skip-self'."
+ (or
+ (= ?> char)
+ (funcall (default-value 'electric-pair-skip-self) char)))
+
+(defun rustic-ordinary-lt-gt-p ()
+ "Test whether the `<' or `>' at point is an ordinary operator of some kind.
+
+This returns t if the `<' or `>' is an ordinary operator (like
+less-than) or part of one (like `->'); and nil if the character
+should be considered a paired angle bracket."
+ (cond
+ ;; If matching is turned off suppress all of them
+ ((not rustic-match-angle-brackets) t)
+
+ ;; This is a cheap check so we do it early.
+ ;; Don't treat the > in -> or => as an angle bracket
+ ((and (= (following-char) ?>) (memq (preceding-char) '(?- ?=))) t)
+
+ ;; We don't take < or > in strings or comments to be angle brackets
+ ((rustic-in-str-or-cmnt) t)
+
+ ;; Inside a macro we don't really know the syntax. Any < or > may be an
+ ;; angle bracket or it may not. But we know that the other braces have
+ ;; to balance regardless of the < and >, so if we don't treat any < or >
+ ;; as angle brackets it won't mess up any paren balancing.
+ ((rustic-in-macro) t)
+
+ ((looking-at "<")
+ (rustic-is-lt-char-operator))
+
+ ((looking-at ">")
+ (cond
+ ;; Don't treat the > in -> or => as an angle bracket
+ ((member (char-before (point)) '(?- ?=)) t)
+
+ ;; If we are at top level and not in any list, it can't be a closing
+ ;; angle bracket
+ ((>= 0 (rustic-paren-level)) t)
+
+ ;; Otherwise, treat the > as a closing angle bracket if it would
+ ;; match an opening one
+ ((save-excursion
+ (backward-up-list)
+ (not (looking-at "<"))))))))
+
+(defun rustic-syntactic-face-function (state)
+ "Return face that distinguishes doc and normal comments in given syntax STATE."
+ (if (nth 3 state)
+ 'font-lock-string-face
+ (save-excursion
+ (goto-char (nth 8 state))
+ (if (looking-at "/\\([*][*!][^*!]\\|/[/!][^/!]\\)")
+ 'font-lock-doc-face
+ 'font-lock-comment-face))))
+
+(eval-and-compile
+ (defconst rustic--char-literal-rx
+ (rx (seq
+ (group "'")
+ (or
+ (seq
+ "\\"
+ (or
+ (: "u{" (** 1 6 xdigit) "}")
+ (: "x" (= 2 xdigit))
+ (any "'nrt0\"\\")))
+ (not (any "'\\")))
+ (group "'")))
+ "A regular expression matching a character literal."))
+
+(defun rustic--syntax-propertize-raw-string (str-start end)
+ "A helper for rustic-syntax-propertize.
+
+This will apply the appropriate string syntax to the character
+from the STR-START up to the end of the raw string, or to END,
+whichever comes first."
+ (when (save-excursion
+ (goto-char str-start)
+ (looking-at "r\\(#*\\)\\(\"\\)"))
+ ;; In a raw string, so try to find the end.
+ (let ((hashes (match-string 1)))
+ ;; Match \ characters at the end of the string to suppress
+ ;; their normal character-quote syntax.
+ (when (re-search-forward (concat "\\(\\\\*\\)\\(\"" hashes "\\)") end t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'syntax-table (string-to-syntax "_"))
+ (put-text-property (1- (match-end 2)) (match-end 2)
+ 'syntax-table (string-to-syntax "|"))
+ (goto-char (match-end 0))))))
+
+(defun rustic-syntax-propertize (start end)
+ "A `syntax-propertize-function' to apply properties from START to END."
+ (let ((rustic-macro-scopes (rustic-macro-scope start end)))
+ (goto-char start)
+ (let ((str-start (rustic-in-str-or-cmnt)))
+ (when str-start
+ (rustic--syntax-propertize-raw-string str-start end)))
+ (funcall
+ (syntax-propertize-rules
+ ;; Character literals.
+ (rustic--char-literal-rx (1 "\"") (2 "\""))
+ ;; Raw strings.
+ ("\\(r\\)#*\""
+ (0 (ignore
+ (goto-char (match-end 0))
+ (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'syntax-table (string-to-syntax "|"))
+ (rustic--syntax-propertize-raw-string (match-beginning 0) end)))))
+ ("[<>]"
+ (0 (ignore
+ (when (save-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (rustic-ordinary-lt-gt-p)))
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'syntax-table (string-to-syntax "."))
+ (goto-char (match-end 0)))))))
+ (point) end)))
+
+(defun rustic-fill-prefix-for-comment-start (line-start)
+ "Determine what to use for `fill-prefix' based on the text at LINE-START."
+ (let ((result
+ ;; Replace /* with same number of spaces
+ (replace-regexp-in-string
+ "\\(?:/\\*+?\\)[!*]?"
+ (lambda (s)
+ ;; We want the * to line up with the first * of the
+ ;; comment start
+ (let ((offset (if (eq t
+ (compare-strings "/*" nil nil
+ s
+ (- (length s) 2)
+ (length s)))
+ 1 2)))
+ (concat (make-string (- (length s) offset)
+ ?\x20) "*")))
+ line-start)))
+ ;; Make sure we've got at least one space at the end
+ (if (not (= (aref result (- (length result) 1)) ?\x20))
+ (setq result (concat result " ")))
+ result))
+
+(defun rustic-in-comment-paragraph (body)
+ ;; We might move the point to fill the next comment, but we don't want it
+ ;; seeming to jump around on the user
+ (save-excursion
+ ;; If we're outside of a comment, with only whitespace and then a comment
+ ;; in front, jump to the comment and prepare to fill it.
+ (when (not (nth 4 (syntax-ppss)))
+ (beginning-of-line)
+ (when (looking-at (concat "[[:space:]\n]*" comment-start-skip))
+ (goto-char (match-end 0))))
+
+ ;; We need this when we're moving the point around and then checking syntax
+ ;; while doing paragraph fills, because the cache it uses isn't always
+ ;; invalidated during this.
+ (syntax-ppss-flush-cache 1)
+ ;; If we're at the beginning of a comment paragraph with nothing but
+ ;; whitespace til the next line, jump to the next line so that we use the
+ ;; existing prefix to figure out what the new prefix should be, rather than
+ ;; inferring it from the comment start.
+ (let ((next-bol (line-beginning-position 2)))
+ (while (save-excursion
+ (end-of-line)
+ (syntax-ppss-flush-cache 1)
+ (and (nth 4 (syntax-ppss))
+ (save-excursion
+ (beginning-of-line)
+ (looking-at paragraph-start))
+ (looking-at "[[:space:]]*$")
+ (nth 4 (syntax-ppss next-bol))))
+ (goto-char next-bol)))
+
+ (syntax-ppss-flush-cache 1)
+ ;; If we're on the last line of a multiline-style comment that started
+ ;; above, back up one line so we don't mistake the * of the */ that ends
+ ;; the comment for a prefix.
+ (when (save-excursion
+ (and (nth 4 (syntax-ppss (line-beginning-position 1)))
+ (looking-at "[[:space:]]*\\*/")))
+ (goto-char (line-end-position 0)))
+ (funcall body)))
+
+(defun rustic-with-comment-fill-prefix (body)
+ (let*
+ ((line-string (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))
+ (line-comment-start
+ (when (nth 4 (syntax-ppss))
+ (cond
+ ;; If we're inside the comment and see a * prefix, use it
+ ((string-match "^\\([[:space:]]*\\*+[[:space:]]*\\)"
+ line-string)
+ (match-string 1 line-string))
+ ;; If we're at the start of a comment, figure out what prefix
+ ;; to use for the subsequent lines after it
+ ((string-match (concat "[[:space:]]*" comment-start-skip) line-string)
+ (rustic-fill-prefix-for-comment-start
+ (match-string 0 line-string))))))
+ (fill-prefix
+ (or line-comment-start
+ fill-prefix)))
+ (funcall body)))
+
+(defun rustic-find-fill-prefix ()
+ (rustic-in-comment-paragraph
+ (lambda ()
+ (rustic-with-comment-fill-prefix
+ (lambda ()
+ fill-prefix)))))
+
+(defun rustic-fill-paragraph (&rest args)
+ "Special wrapping for `fill-paragraph'.
+This handles multi-line comments with a * prefix on each line."
+ (rustic-in-comment-paragraph
+ (lambda ()
+ (rustic-with-comment-fill-prefix
+ (lambda ()
+ (let
+ ((fill-paragraph-function
+ (if (not (eq fill-paragraph-function 'rustic-fill-paragraph))
+ fill-paragraph-function))
+ (fill-paragraph-handle-comment t))
+ (apply 'fill-paragraph args)
+ t))))))
+
+(defun rustic-do-auto-fill (&rest args)
+ "Special wrapping for `do-auto-fill'.
+This handles multi-line comments with a * prefix on each line."
+ (rustic-with-comment-fill-prefix
+ (lambda ()
+ (apply 'do-auto-fill args)
+ t)))
+
+(defun rustic-fill-forward-paragraph (arg)
+ ;; This is to work around some funny behavior when a paragraph separator is
+ ;; at the very top of the file and there is a fill prefix.
+ (let ((fill-prefix nil)) (forward-paragraph arg)))
+
+(defun rustic-comment-indent-new-line (&optional arg)
+ (rustic-with-comment-fill-prefix
+ (lambda () (comment-indent-new-line arg))))
+
+;;; _
+
+(defun rustic-reload ()
+ "Reload rustic package."
+ (interactive)
+ (unload-feature 'rustic)
+ (require 'rustic)
+ (rustic-mode))
+
+(provide 'rustic)
+
+(require 'rustic-interaction)
+
+(defvar rustic-load-optional-libraries t
+ "Whether loading `rustic' also loads optional libraries.
+This variable might soon be remove again.")
+
+(when rustic-load-optional-libraries
+ (require 'rustic-compile)
+ (require 'rustic-popup)
+ (require 'rustic-cargo)
+ (require 'rustic-babel)
+ (require 'rustic-racer)
+ (require 'rustic-rustfmt)
+ (require 'rustic-rustfix)
+ (require 'rustic-playpen)
+ (require 'rustic-lsp)
+ (with-eval-after-load 'flycheck
+ (require 'rustic-flycheck)))
+
+;;; rustic.el ends here
diff --git a/emacs.d/elpa/spinner-1.7.4.signed b/emacs.d/elpa/spinner-1.7.4.signed
new file mode 100644
index 0000000..0771088
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4.signed
@@ -0,0 +1 @@
+Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2021-07-02T12:10:02+0300 using RSA \ No newline at end of file
diff --git a/emacs.d/elpa/spinner-1.7.4/README.org b/emacs.d/elpa/spinner-1.7.4/README.org
new file mode 100644
index 0000000..06c7b32
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/README.org
@@ -0,0 +1,76 @@
+#+TITLE: spinner.el
+
+Add spinners and progress-bars to the mode-line for ongoing operations.
+
+[[file:some-spinners.gif]]
+
+[[file:all-spinners.gif]]
+
+* Usage
+
+First of all, don’t forget to add ~(spinner "VERSION")~ to your package’s dependencies.
+
+** Major-modes
+1. Just call ~(spinner-start)~ and a spinner will be added to the mode-line.
+2. Call ~(spinner-stop)~ on the same buffer when you want to remove it.
+
+The default spinner is a line drawing that rotates. You can pass an
+argument to ~spinner-start~ to specify which spinner you want. All
+possibilities are listed in the ~spinner-types~ variable, but here are
+a few examples for you to try:
+
+- ~(spinner-start 'vertical-breathing 10)~
+- ~(spinner-start 'minibox)~
+- ~(spinner-start 'moon)~
+- ~(spinner-start 'triangle)~
+
+You can also define your own as a vector of strings (see the examples
+in ~spinner-types~).
+
+** Minor-modes
+Minor-modes can create a spinner with ~spinner-create~ and then add it
+to their mode-line lighter. They can then start the spinner by setting
+a variable and calling ~spinner-start-timer~. Finally, they can stop
+the spinner (and the timer) by just setting the same variable to nil.
+
+Here’s an example for a minor-mode named ~foo~. Assuming that
+~foo--lighter~ is used as the mode-line lighter, the following code
+will add an *inactive* global spinner to the mode-line.
+#+begin_src emacs-lisp
+(defvar foo--spinner (spinner-create 'rotating-line))
+(defconst foo--lighter
+ '(" foo" (:eval (spinner-print foo--spinner))))
+#+end_src
+
+1. To activate the spinner, just call ~(spinner-start foo--spinner)~.
+ It will show up on the mode-line and start animating.
+2. To get rid of it, call ~(spinner-stop foo--spinner)~. It will then
+ disappear again.
+
+Some minor-modes will need spinners to be buffer-local. To achieve
+that, just make the ~foo--spinner~ variable buffer-local and use the
+third argument of the ~spinner-create~ function. The snippet below is an example.
+
+#+begin_src emacs-lisp
+(defvar-local foo--spinner nil)
+(defconst foo--lighter
+ '(" foo" (:eval (spinner-print foo--spinner))))
+(defun foo--start-spinner ()
+ "Create and start a spinner on this buffer."
+ (unless foo--spinner
+ (setq foo--spinner (spinner-create 'moon t)))
+ (spinner-start foo--spinner))
+#+end_src
+
+1. To activate the spinner, just call ~(foo--start-spinner)~.
+2. To get rid of it, call ~(spinner-stop foo--spinner)~.
+
+This will use the ~moon~ spinner, but you can use any of the names
+defined in the ~spinner-types~ variable or even define your own.
+
+* Extra options
+
+Both ~spinner-start~ and ~spinner-create~ take extra options to configure the spinner, these are:
+
+- ~FPS~: The number of frames to display per second. Defaults to ~spinner-frames-per-second~.
+- ~DELAY~: After starting a spinner, it still won’t be displayed for this many seconds.
diff --git a/emacs.d/elpa/spinner-1.7.4/all-spinners.gif b/emacs.d/elpa/spinner-1.7.4/all-spinners.gif
new file mode 100644
index 0000000..5540b68
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/all-spinners.gif
Binary files differ
diff --git a/emacs.d/elpa/spinner-1.7.4/some-spinners.gif b/emacs.d/elpa/spinner-1.7.4/some-spinners.gif
new file mode 100644
index 0000000..a8028e7
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/some-spinners.gif
Binary files differ
diff --git a/emacs.d/elpa/spinner-1.7.4/spinner-autoloads.el b/emacs.d/elpa/spinner-1.7.4/spinner-autoloads.el
new file mode 100644
index 0000000..a6cc99a
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/spinner-autoloads.el
@@ -0,0 +1,77 @@
+;;; spinner-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "spinner" "spinner.el" (0 0 0 0))
+;;; Generated autoloads from spinner.el
+
+(autoload 'spinner-create "spinner" "\
+Create a spinner of the given TYPE.
+The possible TYPEs are described in `spinner--type-to-frames'.
+
+FPS, if given, is the number of desired frames per second.
+Default is `spinner-frames-per-second'.
+
+If BUFFER-LOCAL is non-nil, the spinner will be automatically
+deactivated if the buffer is killed. If BUFFER-LOCAL is a
+buffer, use that instead of current buffer.
+
+When started, in order to function properly, the spinner runs a
+timer which periodically calls `force-mode-line-update' in the
+current buffer. If BUFFER-LOCAL was set at creation time, then
+`force-mode-line-update' is called in that buffer instead. When
+the spinner is stopped, the timer is deactivated.
+
+DELAY, if given, is the number of seconds to wait after starting
+the spinner before actually displaying it. It is safe to cancel
+the spinner before this time, in which case it won't display at
+all.
+
+\(fn &optional TYPE BUFFER-LOCAL FPS DELAY)" nil nil)
+
+(autoload 'spinner-start "spinner" "\
+Start a mode-line spinner of given TYPE-OR-OBJECT.
+If TYPE-OR-OBJECT is an object created with `make-spinner',
+simply activate it. This method is designed for minor modes, so
+they can use the spinner as part of their lighter by doing:
+ '(:eval (spinner-print THE-SPINNER))
+To stop this spinner, call `spinner-stop' on it.
+
+If TYPE-OR-OBJECT is anything else, a buffer-local spinner is
+created with this type, and it is displayed in the
+`mode-line-process' of the buffer it was created it. Both
+TYPE-OR-OBJECT and FPS are passed to `make-spinner' (which see).
+To stop this spinner, call `spinner-stop' in the same buffer.
+
+Either way, the return value is a function which can be called
+anywhere to stop this spinner. You can also call `spinner-stop'
+in the same buffer where the spinner was created.
+
+FPS, if given, is the number of desired frames per second.
+Default is `spinner-frames-per-second'.
+
+DELAY, if given, is the number of seconds to wait until actually
+displaying the spinner. It is safe to cancel the spinner before
+this time, in which case it won't display at all.
+
+\(fn &optional TYPE-OR-OBJECT FPS DELAY)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spinner" '("spinner-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("spinner-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; spinner-autoloads.el ends here
diff --git a/emacs.d/elpa/spinner-1.7.4/spinner-pkg.el b/emacs.d/elpa/spinner-1.7.4/spinner-pkg.el
new file mode 100644
index 0000000..2f4bbb7
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/spinner-pkg.el
@@ -0,0 +1,2 @@
+;; Generated package description from spinner.el -*- no-byte-compile: t -*-
+(define-package "spinner" "1.7.4" "Add spinners and progress-bars to the mode-line for ongoing operations" '((emacs "24.3")) :keywords '("processes" "mode-line") :authors '(("Artur Malabarba" . "emacs@endlessparentheses.com")) :maintainer '("Artur Malabarba" . "emacs@endlessparentheses.com") :url "https://github.com/Malabarba/spinner.el")
diff --git a/emacs.d/elpa/spinner-1.7.4/spinner.el b/emacs.d/elpa/spinner-1.7.4/spinner.el
new file mode 100644
index 0000000..6be8f13
--- /dev/null
+++ b/emacs.d/elpa/spinner-1.7.4/spinner.el
@@ -0,0 +1,340 @@
+;;; spinner.el --- Add spinners and progress-bars to the mode-line for ongoing operations -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+;; Version: 1.7.4
+;; Package-Requires: ((emacs "24.3"))
+;; URL: https://github.com/Malabarba/spinner.el
+;; Keywords: processes mode-line
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; 1 Usage
+;; â•â•â•â•â•â•â•
+;;
+;; First of all, don’t forget to add `(spinner "VERSION")' to your
+;; package’s dependencies.
+;;
+;;
+;; 1.1 Major-modes
+;; ───────────────
+;;
+;; 1. Just call `(spinner-start)' and a spinner will be added to the
+;; mode-line.
+;; 2. Call `(spinner-stop)' on the same buffer when you want to remove
+;; it.
+;;
+;; The default spinner is a line drawing that rotates. You can pass an
+;; argument to `spinner-start' to specify which spinner you want. All
+;; possibilities are listed in the `spinner-types' variable, but here are
+;; a few examples for you to try:
+;;
+;; • `(spinner-start 'vertical-breathing 10)'
+;; • `(spinner-start 'minibox)'
+;; • `(spinner-start 'moon)'
+;; • `(spinner-start 'triangle)'
+;;
+;; You can also define your own as a vector of strings (see the examples
+;; in `spinner-types').
+;;
+;;
+;; 1.2 Minor-modes
+;; ───────────────
+;;
+;; Minor-modes can create a spinner with `spinner-create' and then add it
+;; to their mode-line lighter. They can then start the spinner by setting
+;; a variable and calling `spinner-start-timer'. Finally, they can stop
+;; the spinner (and the timer) by just setting the same variable to nil.
+;;
+;; Here’s an example for a minor-mode named `foo'. Assuming that
+;; `foo--lighter' is used as the mode-line lighter, the following code
+;; will add an *inactive* global spinner to the mode-line.
+;; ┌────
+;; │ (defvar foo--spinner (spinner-create 'rotating-line))
+;; │ (defconst foo--lighter
+;; │ '(" foo" (:eval (spinner-print foo--spinner))))
+;; └────
+;;
+;; 1. To activate the spinner, just call `(spinner-start foo--spinner)'.
+;; It will show up on the mode-line and start animating.
+;; 2. To get rid of it, call `(spinner-stop foo--spinner)'. It will then
+;; disappear again.
+;;
+;; Some minor-modes will need spinners to be buffer-local. To achieve
+;; that, just make the `foo--spinner' variable buffer-local and use the
+;; third argument of the `spinner-create' function. The snippet below is an
+;; example.
+;;
+;; ┌────
+;; │ (defvar-local foo--spinner nil)
+;; │ (defconst foo--lighter
+;; │ '(" foo" (:eval (spinner-print foo--spinner))))
+;; │ (defun foo--start-spinner ()
+;; │ "Create and start a spinner on this buffer."
+;; │ (unless foo--spinner
+;; │ (setq foo--spinner (spinner-create 'moon t)))
+;; │ (spinner-start foo--spinner))
+;; └────
+;;
+;; 1. To activate the spinner, just call `(foo--start-spinner)'.
+;; 2. To get rid of it, call `(spinner-stop foo--spinner)'.
+;;
+;; This will use the `moon' spinner, but you can use any of the names
+;; defined in the `spinner-types' variable or even define your own.
+
+
+;;; Code:
+(eval-when-compile
+ (require 'cl-lib))
+
+(defconst spinner-types
+ '((3-line-clock . ["┤" "┘" "â”´" "â””" "├" "┌" "┬" "â”"])
+ (2-line-clock . ["┘" "â””" "┌" "â”"])
+ (flipping-line . ["_" "\\" "|" "/"])
+ (rotating-line . ["-" "\\" "|" "/"])
+ (progress-bar . ["[ ]" "[= ]" "[== ]" "[=== ]" "[====]" "[ ===]" "[ ==]" "[ =]"])
+ (progress-bar-filled . ["| |" "|█ |" "|██ |" "|███ |" "|████|" "| ███|" "| ██|" "| █|"])
+ (vertical-breathing . ["â–" "â–‚" "â–ƒ" "â–„" "â–…" "â–†" "â–‡" "â–ˆ" "â–‡" "â–†" "â–…" "â–„" "â–ƒ" "â–‚" "â–" " "])
+ (vertical-rising . ["â–" "â–„" "â–ˆ" "â–€" "â–”"])
+ (horizontal-breathing . [" " "â–" "â–Ž" "â–" "â–Œ" "â–‹" "â–Š" "â–‰" "â–‰" "â–Š" "â–‹" "â–Œ" "â–" "â–Ž" "â–"])
+ (horizontal-breathing-long
+ . [" " "▎ " "▌ " "▊ " "█ " "█▎" "█▌" "█▊" "██" "█▊" "█▌" "█▎" "█ " "▊ " "▋ " "▌ " "■" "▎ " "■"])
+ (horizontal-moving . [" " "â–Œ " "â–ˆ " "â–â–Œ" " â–ˆ" " â–"])
+ (minibox . ["â––" "â–˜" "â–" "â–—"])
+ (triangle . ["â—¢" "â—£" "â—¤" "â—¥"])
+ (box-in-box . ["â—°" "â—³" "â—²" "â—±"])
+ (box-in-circle . ["â—´" "â—·" "â—¶" "â—µ"])
+ (half-circle . ["â—" "â—“" "â—‘" "â—’"])
+ (moon . ["🌑" "🌘" "🌗" "🌖" "🌕" "🌔" "🌓" "🌒"]))
+ "Predefined alist of spinners.
+Each car is a symbol identifying the spinner, and each cdr is a
+vector, the spinner itself.")
+
+(defun spinner-make-progress-bar (width &optional char)
+ "Return a vector of strings of the given WIDTH.
+The vector is a valid spinner type and is similar to the
+`progress-bar' spinner, except without the surrounding brackets.
+CHAR is the character to use for the moving bar (defaults to =)."
+ (let ((whole-string (concat (make-string (1- width) ?\s)
+ (make-string 4 (or char ?=))
+ (make-string width ?\s))))
+ (apply #'vector (mapcar (lambda (n) (substring whole-string n (+ n width)))
+ (number-sequence (+ width 3) 0 -1)))))
+
+(defvar spinner-current nil
+ "Spinner currently being displayed on the `mode-line-process'.")
+(make-variable-buffer-local 'spinner-current)
+
+(defconst spinner--mode-line-construct
+ '(:eval (spinner-print spinner-current))
+ "Construct used to display a spinner in `mode-line-process'.")
+(put 'spinner--mode-line-construct 'risky-local-variable t)
+
+(defvar spinner-frames-per-second 10
+ "Default speed at which spinners spin, in frames per second.
+Each spinner can override this value.")
+
+
+;;; The spinner object.
+(defun spinner--type-to-frames (type)
+ "Return a vector of frames corresponding to TYPE.
+The list of possible built-in spinner types is given by the
+`spinner-types' variable, but you can also use your own (see
+below).
+
+If TYPE is nil, the frames of this spinner are given by the first
+element of `spinner-types'.
+If TYPE is a symbol, it specifies an element of `spinner-types'.
+If TYPE is 'random, use a random element of `spinner-types'.
+If TYPE is a list, it should be a list of symbols, and a random
+one is chosen as the spinner type.
+If TYPE is a vector, it should be a vector of strings and these
+are used as the spinner's frames. This allows you to make your
+own spinner animations."
+ (cond
+ ((vectorp type) type)
+ ((not type) (cdr (car spinner-types)))
+ ((eq type 'random)
+ (cdr (elt spinner-types
+ (random (length spinner-types)))))
+ ((listp type)
+ (cdr (assq (elt type (random (length type)))
+ spinner-types)))
+ ((symbolp type) (cdr (assq type spinner-types)))
+ (t (error "Unknown spinner type: %s" type))))
+
+(cl-defstruct (spinner
+ (:copier nil)
+ (:conc-name spinner--)
+ (:constructor make-spinner (&optional type buffer-local frames-per-second delay-before-start)))
+ (frames (spinner--type-to-frames type))
+ (counter 0)
+ (fps (or frames-per-second spinner-frames-per-second))
+ (timer (timer-create))
+ (active-p nil)
+ (buffer (when buffer-local
+ (if (bufferp buffer-local)
+ buffer-local
+ (current-buffer))))
+ (delay (or delay-before-start 0)))
+
+;;;###autoload
+(defun spinner-create (&optional type buffer-local fps delay)
+ "Create a spinner of the given TYPE.
+The possible TYPEs are described in `spinner--type-to-frames'.
+
+FPS, if given, is the number of desired frames per second.
+Default is `spinner-frames-per-second'.
+
+If BUFFER-LOCAL is non-nil, the spinner will be automatically
+deactivated if the buffer is killed. If BUFFER-LOCAL is a
+buffer, use that instead of current buffer.
+
+When started, in order to function properly, the spinner runs a
+timer which periodically calls `force-mode-line-update' in the
+current buffer. If BUFFER-LOCAL was set at creation time, then
+`force-mode-line-update' is called in that buffer instead. When
+the spinner is stopped, the timer is deactivated.
+
+DELAY, if given, is the number of seconds to wait after starting
+the spinner before actually displaying it. It is safe to cancel
+the spinner before this time, in which case it won't display at
+all."
+ (make-spinner type buffer-local fps delay))
+
+(defun spinner-print (spinner)
+ "Return a string of the current frame of SPINNER.
+If SPINNER is nil, just return nil.
+Designed to be used in the mode-line with:
+ (:eval (spinner-print some-spinner))"
+ (when (and spinner (spinner--active-p spinner))
+ (let ((frame (spinner--counter spinner)))
+ (when (>= frame 0)
+ (elt (spinner--frames spinner) frame)))))
+
+(defun spinner--timer-function (spinner)
+ "Function called to update SPINNER.
+If SPINNER is no longer active, or if its buffer has been killed,
+stop the SPINNER's timer."
+ (let ((buffer (spinner--buffer spinner)))
+ (if (or (not (spinner--active-p spinner))
+ (and buffer (not (buffer-live-p buffer))))
+ (spinner-stop spinner)
+ ;; Increment
+ (cl-callf (lambda (x) (if (< x 0)
+ (1+ x)
+ (% (1+ x) (length (spinner--frames spinner)))))
+ (spinner--counter spinner))
+ ;; Update mode-line.
+ (if (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (force-mode-line-update))
+ (force-mode-line-update)))))
+
+(defun spinner--start-timer (spinner)
+ "Start a SPINNER's timer."
+ (let ((old-timer (spinner--timer spinner)))
+ (when (timerp old-timer)
+ (cancel-timer old-timer))
+
+ (setf (spinner--active-p spinner) t)
+
+ (unless (ignore-errors (> (spinner--fps spinner) 0))
+ (error "A spinner's FPS must be a positive number"))
+ (setf (spinner--counter spinner)
+ (round (- (* (or (spinner--delay spinner) 0)
+ (spinner--fps spinner)))))
+ ;; Create timer.
+ (let* ((repeat (/ 1.0 (spinner--fps spinner)))
+ (time (timer-next-integral-multiple-of-time (current-time) repeat))
+ ;; Create the timer as a lex variable so it can cancel itself.
+ (timer (spinner--timer spinner)))
+ (timer-set-time timer time repeat)
+ (timer-set-function timer #'spinner--timer-function (list spinner))
+ (timer-activate timer)
+ ;; Return a stopping function.
+ (lambda () (spinner-stop spinner)))))
+
+
+;;; The main functions
+;;;###autoload
+(defun spinner-start (&optional type-or-object fps delay)
+ "Start a mode-line spinner of given TYPE-OR-OBJECT.
+If TYPE-OR-OBJECT is an object created with `make-spinner',
+simply activate it. This method is designed for minor modes, so
+they can use the spinner as part of their lighter by doing:
+ '(:eval (spinner-print THE-SPINNER))
+To stop this spinner, call `spinner-stop' on it.
+
+If TYPE-OR-OBJECT is anything else, a buffer-local spinner is
+created with this type, and it is displayed in the
+`mode-line-process' of the buffer it was created it. Both
+TYPE-OR-OBJECT and FPS are passed to `make-spinner' (which see).
+To stop this spinner, call `spinner-stop' in the same buffer.
+
+Either way, the return value is a function which can be called
+anywhere to stop this spinner. You can also call `spinner-stop'
+in the same buffer where the spinner was created.
+
+FPS, if given, is the number of desired frames per second.
+Default is `spinner-frames-per-second'.
+
+DELAY, if given, is the number of seconds to wait until actually
+displaying the spinner. It is safe to cancel the spinner before
+this time, in which case it won't display at all."
+ (unless (spinner-p type-or-object)
+ ;; Choose type.
+ (if (spinner-p spinner-current)
+ (setf (spinner--frames spinner-current) (spinner--type-to-frames type-or-object))
+ (setq spinner-current (make-spinner type-or-object (current-buffer) fps delay)))
+ (setq type-or-object spinner-current)
+ ;; Maybe add to mode-line.
+ (unless (and (listp mode-line-process)
+ (memq 'spinner--mode-line-construct mode-line-process))
+ (setq mode-line-process
+ (list (or mode-line-process "")
+ 'spinner--mode-line-construct))))
+
+ ;; Create timer.
+ (when fps (setf (spinner--fps type-or-object) fps))
+ (when delay (setf (spinner--delay type-or-object) delay))
+ (spinner--start-timer type-or-object))
+
+(defun spinner-start-print (spinner)
+ "Like `spinner-print', but also start SPINNER if it's not active."
+ (unless (spinner--active-p spinner)
+ (spinner-start spinner))
+ (spinner-print spinner))
+
+(defun spinner-stop (&optional spinner)
+ "Stop SPINNER, defaulting to the current buffer's spinner.
+It is always safe to call this function, even if there is no
+active spinner."
+ (let ((spinner (or spinner spinner-current)))
+ (when (spinner-p spinner)
+ (let ((timer (spinner--timer spinner)))
+ (when (timerp timer)
+ (cancel-timer timer)))
+ (setf (spinner--active-p spinner) nil)
+ (force-mode-line-update))))
+
+(provide 'spinner)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+;;; spinner.el ends here
diff --git a/emacs.d/elpa/xref-1.1.0.signed b/emacs.d/elpa/xref-1.1.0.signed
new file mode 100644
index 0000000..f4efdd2
--- /dev/null
+++ b/emacs.d/elpa/xref-1.1.0.signed
@@ -0,0 +1 @@
+Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2021-04-29T12:05:02+0300 using RSA \ No newline at end of file
diff --git a/emacs.d/elpa/xref-1.1.0/xref-autoloads.el b/emacs.d/elpa/xref-1.1.0/xref-autoloads.el
new file mode 100644
index 0000000..9cf959d
--- /dev/null
+++ b/emacs.d/elpa/xref-1.1.0/xref-autoloads.el
@@ -0,0 +1,110 @@
+;;; xref-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "xref" "xref.el" (0 0 0 0))
+;;; Generated autoloads from xref.el
+
+(autoload 'xref-find-backend "xref" nil nil nil)
+
+(autoload 'xref-pop-marker-stack "xref" "\
+Pop back to where \\[xref-find-definitions] was last invoked." t nil)
+
+(autoload 'xref-marker-stack-empty-p "xref" "\
+Return t if the marker stack is empty; nil otherwise." nil nil)
+
+(autoload 'xref-find-definitions "xref" "\
+Find the definition of the identifier at point.
+With prefix argument or when there's no identifier at point,
+prompt for it.
+
+If sufficient information is available to determine a unique
+definition for IDENTIFIER, display it in the selected window.
+Otherwise, display the list of the possible definitions in a
+buffer where the user can select from the list.
+
+\(fn IDENTIFIER)" t nil)
+
+(autoload 'xref-find-definitions-other-window "xref" "\
+Like `xref-find-definitions' but switch to the other window.
+
+\(fn IDENTIFIER)" t nil)
+
+(autoload 'xref-find-definitions-other-frame "xref" "\
+Like `xref-find-definitions' but switch to the other frame.
+
+\(fn IDENTIFIER)" t nil)
+
+(autoload 'xref-find-references "xref" "\
+Find references to the identifier at point.
+This command might prompt for the identifier as needed, perhaps
+offering the symbol at point as the default.
+With prefix argument, or if `xref-prompt-for-identifier' is t,
+always prompt for the identifier. If `xref-prompt-for-identifier'
+is nil, prompt only if there's no usable symbol at point.
+
+\(fn IDENTIFIER)" t nil)
+
+(autoload 'xref-find-definitions-at-mouse "xref" "\
+Find the definition of identifier at or around mouse click.
+This command is intended to be bound to a mouse event.
+
+\(fn EVENT)" t nil)
+
+(autoload 'xref-find-apropos "xref" "\
+Find all meaningful symbols that match PATTERN.
+The argument has the same meaning as in `apropos'.
+
+\(fn PATTERN)" t nil)
+ (define-key esc-map "." #'xref-find-definitions)
+ (define-key esc-map "," #'xref-pop-marker-stack)
+ (define-key esc-map "?" #'xref-find-references)
+ (define-key esc-map [?\C-.] #'xref-find-apropos)
+ (define-key ctl-x-4-map "." #'xref-find-definitions-other-window)
+ (define-key ctl-x-5-map "." #'xref-find-definitions-other-frame)
+
+(autoload 'xref-references-in-directory "xref" "\
+Find all references to SYMBOL in directory DIR.
+Return a list of xref values.
+
+This function uses the Semantic Symbol Reference API, see
+`semantic-symref-tool-alist' for details on which tools are used,
+and when.
+
+\(fn SYMBOL DIR)" nil nil)
+
+(autoload 'xref-matches-in-directory "xref" "\
+Find all matches for REGEXP in directory DIR.
+Return a list of xref values.
+Only files matching some of FILES and none of IGNORES are searched.
+FILES is a string with glob patterns separated by spaces.
+IGNORES is a list of glob patterns for files to ignore.
+
+\(fn REGEXP FILES DIR IGNORES)" nil nil)
+
+(autoload 'xref-matches-in-files "xref" "\
+Find all matches for REGEXP in FILES.
+Return a list of xref values.
+FILES must be a list of absolute file names.
+
+\(fn REGEXP FILES)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xref" '("xref-")))
+
+;;;***
+
+;;;### (autoloads nil nil ("xref-pkg.el") (0 0 0 0))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; xref-autoloads.el ends here
diff --git a/emacs.d/elpa/xref-1.1.0/xref-pkg.el b/emacs.d/elpa/xref-1.1.0/xref-pkg.el
new file mode 100644
index 0000000..a51b51b
--- /dev/null
+++ b/emacs.d/elpa/xref-1.1.0/xref-pkg.el
@@ -0,0 +1,2 @@
+;; Generated package description from xref.el -*- no-byte-compile: t -*-
+(define-package "xref" "1.1.0" "Cross-referencing commands" '((emacs "26.1")) :url "https://elpa.gnu.org/packages/xref.html")
diff --git a/emacs.d/elpa/xref-1.1.0/xref.el b/emacs.d/elpa/xref-1.1.0/xref.el
new file mode 100644
index 0000000..7fc7181
--- /dev/null
+++ b/emacs.d/elpa/xref-1.1.0/xref.el
@@ -0,0 +1,1744 @@
+;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
+
+;; Copyright (C) 2014-2021 Free Software Foundation, Inc.
+;; Version: 1.1.0
+;; Package-Requires: ((emacs "26.1"))
+
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file provides a somewhat generic infrastructure for cross
+;; referencing commands, in particular "find-definition".
+;;
+;; Some part of the functionality must be implemented in a language
+;; dependent way and that's done by defining an xref backend.
+;;
+;; That consists of a constructor function, which should return a
+;; backend value, and a set of implementations for the generic
+;; functions:
+;;
+;; `xref-backend-identifier-at-point',
+;; `xref-backend-identifier-completion-table',
+;; `xref-backend-definitions', `xref-backend-references',
+;; `xref-backend-apropos', which see.
+;;
+;; A major mode would normally use `add-hook' to add the backend
+;; constructor to `xref-backend-functions'.
+;;
+;; The last three methods operate with "xref" and "location" values.
+;;
+;; One would usually call `make-xref' and `xref-make-file-location',
+;; `xref-make-buffer-location' or `xref-make-bogus-location' to create
+;; them. More generally, a location must be an instance of an EIEIO
+;; class inheriting from `xref-location' and implementing
+;; `xref-location-group' and `xref-location-marker'.
+;;
+;; There's a special kind of xrefs we call "match xrefs", which
+;; correspond to search results. For these values,
+;; `xref-match-length' must be defined, and `xref-location-marker'
+;; must return the beginning of the match.
+;;
+;; Each identifier must be represented as a string. Implementers can
+;; use string properties to store additional information about the
+;; identifier, but they should keep in mind that values returned from
+;; `xref-backend-identifier-completion-table' should still be
+;; distinct, because the user can't see the properties when making the
+;; choice.
+;;
+;; See the etags and elisp-mode implementations for full examples.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'eieio)
+(require 'ring)
+(require 'project)
+
+(defgroup xref nil "Cross-referencing commands"
+ :version "25.1"
+ :group 'tools)
+
+
+;;; Locations
+
+(defclass xref-location () ()
+ :documentation "A location represents a position in a file or buffer.")
+
+(cl-defgeneric xref-location-marker (location)
+ "Return the marker for LOCATION.")
+
+(cl-defgeneric xref-location-group (location)
+ "Return a string used to group a set of locations.
+This is typically the filename.")
+
+(cl-defgeneric xref-location-line (_location)
+ "Return the line number corresponding to the location."
+ nil)
+
+(cl-defgeneric xref-match-length (_item)
+ "Return the length of the match."
+ nil)
+
+;;;; Commonly needed location classes are defined here:
+
+(defcustom xref-file-name-display 'project-relative
+ "Style of file name display in *xref* buffers.
+
+If the value is the symbol `abs', the default, show the file names
+in their full absolute form.
+
+If `nondirectory', show only the nondirectory (a.k.a. \"base name\")
+part of the file name.
+
+If `project-relative', show only the file name relative to the
+current project root. If there is no current project, or if the
+file resides outside of its root, show that particular file name
+in its full absolute form."
+ :type '(choice (const :tag "absolute file name" abs)
+ (const :tag "nondirectory file name" nondirectory)
+ (const :tag "relative to project root" project-relative))
+ :version "27.1")
+
+;; FIXME: might be useful to have an optional "hint" i.e. a string to
+;; search for in case the line number is slightly out of date.
+(defclass xref-file-location (xref-location)
+ ((file :type string :initarg :file)
+ (line :type fixnum :initarg :line :reader xref-location-line)
+ (column :type fixnum :initarg :column :reader xref-file-location-column))
+ :documentation "A file location is a file/line/column triple.
+Line numbers start from 1 and columns from 0.")
+
+(defun xref-make-file-location (file line column)
+ "Create and return a new `xref-file-location'."
+ (make-instance 'xref-file-location :file file :line line :column column))
+
+(cl-defmethod xref-location-marker ((l xref-file-location))
+ (with-slots (file line column) l
+ (with-current-buffer
+ (or (get-file-buffer file)
+ (let ((find-file-suppress-same-file-warnings t))
+ (find-file-noselect file)))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char (point-min))
+ (ignore-errors
+ ;; xref location may be out of date; it may be past the
+ ;; end of the current file, or the file may have been
+ ;; deleted. Return a reasonable location; the user will
+ ;; figure it out.
+ (beginning-of-line line)
+ (forward-char column))
+ (point-marker))))))
+
+(defvar xref--project-root-memo nil
+ "Cons mapping `default-directory' value to the search root.")
+
+(cl-defmethod xref-location-group ((l xref-file-location))
+ (cl-ecase xref-file-name-display
+ (abs
+ (oref l file))
+ (nondirectory
+ (file-name-nondirectory (oref l file)))
+ (project-relative
+ (unless (and xref--project-root-memo
+ (equal (car xref--project-root-memo)
+ default-directory))
+ (setq xref--project-root-memo
+ (cons default-directory
+ (let ((root
+ (let ((pr (project-current)))
+ (and pr (xref--project-root pr)))))
+ (and root (expand-file-name root))))))
+ (let ((file (oref l file))
+ (search-root (cdr xref--project-root-memo)))
+ (if (and search-root
+ (string-prefix-p search-root file))
+ (substring file (length search-root))
+ file)))))
+
+(defclass xref-buffer-location (xref-location)
+ ((buffer :type buffer :initarg :buffer)
+ (position :type fixnum :initarg :position)))
+
+(defun xref-make-buffer-location (buffer position)
+ "Create and return a new `xref-buffer-location'."
+ (make-instance 'xref-buffer-location :buffer buffer :position position))
+
+(cl-defmethod xref-location-marker ((l xref-buffer-location))
+ (with-slots (buffer position) l
+ (let ((m (make-marker)))
+ (move-marker m position buffer))))
+
+(cl-defmethod xref-location-group ((l xref-buffer-location))
+ (with-slots (buffer) l
+ (or (buffer-file-name buffer)
+ (format "(buffer %s)" (buffer-name buffer)))))
+
+(defclass xref-bogus-location (xref-location)
+ ((message :type string :initarg :message
+ :reader xref-bogus-location-message))
+ :documentation "Bogus locations are sometimes useful to
+indicate errors, e.g. when we know that a function exists but the
+actual location is not known.")
+
+(defun xref-make-bogus-location (message)
+ "Create and return a new `xref-bogus-location'."
+ (make-instance 'xref-bogus-location :message message))
+
+(cl-defmethod xref-location-marker ((l xref-bogus-location))
+ (user-error "%s" (oref l message)))
+
+(cl-defmethod xref-location-group ((_ xref-bogus-location)) "(No location)")
+
+
+;;; Cross-reference
+
+(defclass xref-item ()
+ ((summary :type string :initarg :summary
+ :reader xref-item-summary
+ :documentation "One line which will be displayed for
+this item in the output buffer.")
+ (location :initarg :location
+ :reader xref-item-location
+ :documentation "An object describing how to navigate
+to the reference's target."))
+ :comment "An xref item describes a reference to a location
+somewhere.")
+
+(defun xref-make (summary location)
+ "Create and return a new `xref-item'.
+SUMMARY is a short string to describe the xref.
+LOCATION is an `xref-location'."
+ (make-instance 'xref-item :summary summary :location location))
+
+(defclass xref-match-item ()
+ ((summary :type string :initarg :summary
+ :reader xref-item-summary)
+ (location :initarg :location
+ :type xref-file-location
+ :reader xref-item-location)
+ (length :initarg :length :reader xref-match-length))
+ :comment "A match xref item describes a search result.")
+
+(defun xref-make-match (summary location length)
+ "Create and return a new `xref-match-item'.
+SUMMARY is a short string to describe the xref.
+LOCATION is an `xref-location'.
+LENGTH is the match length, in characters."
+ (make-instance 'xref-match-item :summary summary
+ :location location :length length))
+
+
+;;; API
+
+(defvar xref-backend-functions nil
+ "Special hook to find the xref backend for the current context.
+Each function on this hook is called in turn with no arguments,
+and should return either nil to mean that it is not applicable,
+or an xref backend, which is a value to be used to dispatch the
+generic functions.")
+
+;; We make the etags backend the default for now, until something
+;; better comes along. Use APPEND so that any `add-hook' calls made
+;; before this package is loaded put new items before this one.
+(add-hook 'xref-backend-functions #'etags--xref-backend t)
+
+;;;###autoload
+(defun xref-find-backend ()
+ (run-hook-with-args-until-success 'xref-backend-functions))
+
+(cl-defgeneric xref-backend-definitions (backend identifier)
+ "Find definitions of IDENTIFIER.
+
+The result must be a list of xref objects. If IDENTIFIER
+contains sufficient information to determine a unique definition,
+return only that definition. If there are multiple possible
+definitions, return all of them. If no definitions can be found,
+return nil.
+
+IDENTIFIER can be any string returned by
+`xref-backend-identifier-at-point', or from the table returned by
+`xref-backend-identifier-completion-table'.
+
+To create an xref object, call `xref-make'.")
+
+(cl-defgeneric xref-backend-references (_backend identifier)
+ "Find references of IDENTIFIER.
+The result must be a list of xref objects. If no references can
+be found, return nil.
+
+The default implementation uses `semantic-symref-tool-alist' to
+find a search tool; by default, this uses \"find | grep\" in the
+current project's main and external roots."
+ (mapcan
+ (lambda (dir)
+ (xref-references-in-directory identifier dir))
+ (let ((pr (project-current t)))
+ (cons
+ (xref--project-root pr)
+ (project-external-roots pr)))))
+
+(cl-defgeneric xref-backend-apropos (backend pattern)
+ "Find all symbols that match PATTERN string.
+The second argument has the same meaning as in `apropos'.
+
+If BACKEND is implemented in Lisp, it can use
+`xref-apropos-regexp' to convert the pattern to regexp.")
+
+(cl-defgeneric xref-backend-identifier-at-point (_backend)
+ "Return the relevant identifier at point.
+
+The return value must be a string, or nil meaning no identifier
+at point found.
+
+If it's hard to determine the identifier precisely (e.g., because
+it's a method call on unknown type), the implementation can
+return a simple string (such as symbol at point) marked with a
+special text property which e.g. `xref-backend-definitions' would
+recognize and then delegate the work to an external process."
+ (let ((thing (thing-at-point 'symbol)))
+ (and thing (substring-no-properties thing))))
+
+(cl-defgeneric xref-backend-identifier-completion-table (backend)
+ "Return the completion table for identifiers.")
+
+(cl-defgeneric xref-backend-identifier-completion-ignore-case (_backend)
+ "Return t if case is not significant in identifier completion."
+ completion-ignore-case)
+
+
+;;; misc utilities
+(defun xref--alistify (list key test)
+ "Partition the elements of LIST into an alist.
+KEY extracts the key from an element and TEST is used to compare
+keys."
+ (let ((alist '()))
+ (dolist (e list)
+ (let* ((k (funcall key e))
+ (probe (cl-assoc k alist :test test)))
+ (if probe
+ (setcdr probe (cons e (cdr probe)))
+ (push (cons k (list e)) alist))))
+ ;; Put them back in order.
+ (cl-loop for (key . value) in (reverse alist)
+ collect (cons key (reverse value)))))
+
+(defun xref--insert-propertized (props &rest strings)
+ "Insert STRINGS with text properties PROPS."
+ (let ((start (point)))
+ (apply #'insert strings)
+ (add-text-properties start (point) props)))
+
+(defun xref--search-property (property &optional backward)
+ "Search the next text range where text property PROPERTY is non-nil.
+Return the value of PROPERTY. If BACKWARD is non-nil, search
+backward."
+ (let ((next (if backward
+ #'previous-single-char-property-change
+ #'next-single-char-property-change))
+ (start (point))
+ (value nil))
+ (while (progn
+ (goto-char (funcall next (point) property))
+ (not (or (setq value (get-text-property (point) property))
+ (eobp)
+ (bobp)))))
+ (cond (value)
+ (t (goto-char start) nil))))
+
+
+;;; Marker stack (M-. pushes, M-, pops)
+
+(defcustom xref-marker-ring-length 16
+ "Length of the xref marker ring.
+If this variable is not set through Customize, you must call
+`xref-set-marker-ring-length' for changes to take effect."
+ :type 'integer
+ :initialize #'custom-initialize-default
+ :set #'xref-set-marker-ring-length)
+
+(defcustom xref-prompt-for-identifier '(not xref-find-definitions
+ xref-find-definitions-other-window
+ xref-find-definitions-other-frame)
+ "If non-nil, prompt for the identifier to find.
+
+When t, always prompt for the identifier name.
+
+When nil, prompt only when there's no value at point we can use,
+or when the command has been called with the prefix argument.
+
+Otherwise, it's a list of xref commands which will always prompt,
+with the identifier at point, if any, used as the default.
+If the list starts with `not', the meaning of the rest of the
+elements is negated: these commands will NOT prompt."
+ :type '(choice (const :tag "Always prompt for identifier" t)
+ (const :tag "Prompt if no identifier at point" nil)
+ (set :menu-tag "Prompt according to command"
+ :tag "Prompt according to command"
+ :value (not)
+ (const :tag "Except for commands listed below" not)
+ (repeat :inline t (symbol :tag "command")))))
+
+(defcustom xref-after-jump-hook '(recenter
+ xref-pulse-momentarily)
+ "Functions called after jumping to an xref."
+ :type 'hook)
+
+(defcustom xref-after-return-hook '(xref-pulse-momentarily)
+ "Functions called after returning to a pre-jump location."
+ :type 'hook)
+
+(defcustom xref-after-update-hook nil
+ "Functions called after the xref buffer is updated."
+ :type 'hook
+ :version "28.1"
+ :package-version '(xref . "1.0.4"))
+
+(defvar xref--marker-ring (make-ring xref-marker-ring-length)
+ "Ring of markers to implement the marker stack.")
+
+(defun xref-set-marker-ring-length (var val)
+ "Set `xref-marker-ring-length'.
+VAR is the symbol `xref-marker-ring-length' and VAL is the new
+value."
+ (set-default var val)
+ (if (ring-p xref--marker-ring)
+ (ring-resize xref--marker-ring val)))
+
+(defun xref-push-marker-stack (&optional m)
+ "Add point M (defaults to `point-marker') to the marker stack."
+ (ring-insert xref--marker-ring (or m (point-marker))))
+
+;;;###autoload
+(defun xref-pop-marker-stack ()
+ "Pop back to where \\[xref-find-definitions] was last invoked."
+ (interactive)
+ (let ((ring xref--marker-ring))
+ (when (ring-empty-p ring)
+ (user-error "Marker stack is empty"))
+ (let ((marker (ring-remove ring 0)))
+ (switch-to-buffer (or (marker-buffer marker)
+ (user-error "The marked buffer has been deleted")))
+ (goto-char (marker-position marker))
+ (set-marker marker nil nil)
+ (run-hooks 'xref-after-return-hook))))
+
+(defvar xref--current-item nil)
+
+(defun xref-pulse-momentarily ()
+ (pcase-let ((`(,beg . ,end)
+ (save-excursion
+ (or
+ (let ((length (xref-match-length xref--current-item)))
+ (and length (cons (point) (+ (point) length))))
+ (back-to-indentation)
+ (if (eolp)
+ (cons (line-beginning-position) (1+ (point)))
+ (cons (point) (line-end-position)))))))
+ (pulse-momentary-highlight-region beg end 'next-error)))
+
+;; etags.el needs this
+(defun xref-clear-marker-stack ()
+ "Discard all markers from the marker stack."
+ (let ((ring xref--marker-ring))
+ (while (not (ring-empty-p ring))
+ (let ((marker (ring-remove ring)))
+ (set-marker marker nil nil)))))
+
+;;;###autoload
+(defun xref-marker-stack-empty-p ()
+ "Return t if the marker stack is empty; nil otherwise."
+ (ring-empty-p xref--marker-ring))
+
+
+
+(defun xref--goto-char (pos)
+ (cond
+ ((and (<= (point-min) pos) (<= pos (point-max))))
+ (widen-automatically (widen))
+ (t (user-error "Position is outside accessible part of buffer")))
+ (goto-char pos))
+
+(defun xref--goto-location (location)
+ "Set buffer and point according to xref-location LOCATION."
+ (let ((marker (xref-location-marker location)))
+ (set-buffer (marker-buffer marker))
+ (xref--goto-char marker)))
+
+(defun xref-pop-to-location (item &optional action)
+ "Go to the location of ITEM and display the buffer.
+ACTION controls how the buffer is displayed:
+ nil -- switch-to-buffer
+ `window' -- pop-to-buffer (other window)
+ `frame' -- pop-to-buffer (other frame)
+If SELECT is non-nil, select the target window."
+ (let* ((marker (save-excursion
+ (xref-location-marker (xref-item-location item))))
+ (buf (marker-buffer marker)))
+ (cl-ecase action
+ ((nil) (switch-to-buffer buf))
+ (window (pop-to-buffer buf t))
+ (frame (let ((pop-up-frames t)) (pop-to-buffer buf t))))
+ (xref--goto-char marker))
+ (let ((xref--current-item item))
+ (run-hooks 'xref-after-jump-hook)))
+
+
+;;; XREF buffer (part of the UI)
+
+;; The xref buffer is used to display a set of xrefs.
+(defconst xref-buffer-name "*xref*"
+ "The name of the buffer to show xrefs.")
+
+(defface xref-file-header '((t :inherit compilation-info))
+ "Face used to highlight file header in the xref buffer."
+ :version "27.1")
+
+(defface xref-line-number '((t :inherit compilation-line-number))
+ "Face for displaying line numbers in the xref buffer."
+ :version "27.1")
+
+(defface xref-match '((t :inherit match))
+ "Face used to highlight matches in the xref buffer."
+ :version "27.1")
+
+(defmacro xref--with-dedicated-window (&rest body)
+ `(let* ((xref-w (get-buffer-window xref-buffer-name))
+ (xref-w-dedicated (window-dedicated-p xref-w)))
+ (unwind-protect
+ (progn
+ (when xref-w
+ (set-window-dedicated-p xref-w 'soft))
+ ,@body)
+ (when xref-w
+ (set-window-dedicated-p xref-w xref-w-dedicated)))))
+
+(defvar-local xref--original-window-intent nil
+ "Original window-switching intent before xref buffer creation.")
+
+(defvar-local xref--original-window nil
+ "The original window this xref buffer was created from.")
+
+(defvar-local xref--fetcher nil
+ "The original function to call to fetch the list of xrefs.")
+
+(defun xref--show-pos-in-buf (pos buf)
+ "Goto and display position POS of buffer BUF in a window.
+Honor `xref--original-window-intent', run `xref-after-jump-hook'
+and finally return the window."
+ (let* ((pop-up-frames
+ (or (eq xref--original-window-intent 'frame)
+ pop-up-frames))
+ (action
+ (cond ((eq xref--original-window-intent 'frame)
+ t)
+ ((eq xref--original-window-intent 'window)
+ `((xref--display-buffer-in-other-window)
+ (window . ,xref--original-window)))
+ ((and
+ (window-live-p xref--original-window)
+ (or (not (window-dedicated-p xref--original-window))
+ (eq (window-buffer xref--original-window) buf)))
+ `((xref--display-buffer-in-window)
+ (window . ,xref--original-window))))))
+ (with-selected-window (display-buffer buf action)
+ (xref--goto-char pos)
+ (run-hooks 'xref-after-jump-hook)
+ (selected-window))))
+
+(defun xref--display-buffer-in-other-window (buffer alist)
+ (let ((window (assoc-default 'window alist)))
+ (cl-assert window)
+ (xref--with-dedicated-window
+ (with-selected-window window
+ (display-buffer buffer t)))))
+
+(defun xref--display-buffer-in-window (buffer alist)
+ (let ((window (assoc-default 'window alist)))
+ (cl-assert window)
+ (with-selected-window window
+ (display-buffer buffer '(display-buffer-same-window)))))
+
+(defun xref--show-location (location &optional select)
+ "Help `xref-show-xref' and `xref-goto-xref' do their job.
+Go to LOCATION and if SELECT is non-nil select its window. If
+SELECT is `quit', also quit the *xref* window."
+ (condition-case err
+ (let* ((marker (xref-location-marker location))
+ (buf (marker-buffer marker))
+ (xref-buffer (current-buffer)))
+ (cond (select
+ (if (eq select 'quit) (quit-window nil nil))
+ (select-window
+ (with-current-buffer xref-buffer
+ (xref--show-pos-in-buf marker buf))))
+ (t
+ (save-selected-window
+ (xref--with-dedicated-window
+ (xref--show-pos-in-buf marker buf))))))
+ (user-error (message (error-message-string err)))))
+
+(defun xref-show-location-at-point ()
+ "Display the source of xref at point in the appropriate window, if any."
+ (interactive)
+ (let* ((xref (xref--item-at-point))
+ (xref--current-item xref))
+ (when xref
+ (xref--show-location (xref-item-location xref)))))
+
+(defun xref-next-line-no-show ()
+ "Move to the next xref but don't display its source."
+ (interactive)
+ (xref--search-property 'xref-item))
+
+(defun xref-next-line ()
+ "Move to the next xref and display its source in the appropriate window."
+ (interactive)
+ (xref-next-line-no-show)
+ (xref-show-location-at-point))
+
+(defun xref-prev-line-no-show ()
+ "Move to the previous xref but don't display its source."
+ (interactive)
+ (xref--search-property 'xref-item t))
+
+(defun xref-prev-line ()
+ "Move to the previous xref and display its source in the appropriate window."
+ (interactive)
+ (xref-prev-line-no-show)
+ (xref-show-location-at-point))
+
+(defun xref-next-group ()
+ "Move to the first item of the next xref group and display its source."
+ (interactive)
+ (xref--search-property 'xref-group)
+ (xref--search-property 'xref-item)
+ (xref-show-location-at-point))
+
+(defun xref-prev-group ()
+ "Move to the first item of the previous xref group and display its source."
+ (interactive)
+ ;; Search for the xref group of the current item, provided that the
+ ;; point is not already in an xref group.
+ (unless (plist-member (text-properties-at (point)) 'xref-group)
+ (xref--search-property 'xref-group t))
+ ;; Search for the previous xref group.
+ (xref--search-property 'xref-group t)
+ (xref--search-property 'xref-item)
+ (xref-show-location-at-point))
+
+(defun xref--item-at-point ()
+ (get-text-property
+ (if (eolp) (1- (point)) (point))
+ 'xref-item))
+
+(defun xref-goto-xref (&optional quit)
+ "Jump to the xref on the current line and select its window.
+If QUIT is non-nil (interactively, with prefix argument), also
+quit the *xref* buffer."
+ (interactive "P")
+ (let* ((buffer (current-buffer))
+ (xref (or (xref--item-at-point)
+ (user-error "No reference at point")))
+ (xref--current-item xref))
+ (xref--show-location (xref-item-location xref) (if quit 'quit t))
+ (if (fboundp 'next-error-found)
+ (next-error-found buffer (current-buffer))
+ ;; Emacs < 27
+ (setq next-error-last-buffer buffer))))
+
+(defun xref-quit-and-goto-xref ()
+ "Quit *xref* buffer, then jump to xref on current line."
+ (interactive)
+ (xref-goto-xref t))
+
+(defun xref-quit-and-pop-marker-stack ()
+ "Quit *xref* buffer, then pop the xref marker stack."
+ (interactive)
+ (quit-window)
+ (xref-pop-marker-stack))
+
+(defun xref-query-replace-in-results (from to)
+ "Perform interactive replacement of FROM with TO in all displayed xrefs.
+
+This command interactively replaces FROM with TO in the names of the
+references displayed in the current *xref* buffer."
+ (interactive
+ (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
+ (list fr
+ (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
+ (let* (item xrefs iter)
+ (save-excursion
+ (while (setq item (xref--search-property 'xref-item))
+ (when (xref-match-length item)
+ (push item xrefs))))
+ (unwind-protect
+ (progn
+ (goto-char (point-min))
+ (setq iter (xref--buf-pairs-iterator (nreverse xrefs)))
+ (xref--query-replace-1 from to iter))
+ (funcall iter :cleanup))))
+
+(defun xref--buf-pairs-iterator (xrefs)
+ (let (chunk-done item next-pair file-buf pairs all-pairs)
+ (lambda (action)
+ (pcase action
+ (:next
+ (when (or xrefs next-pair)
+ (setq chunk-done nil)
+ (when next-pair
+ (setq file-buf (marker-buffer (car next-pair))
+ pairs (list next-pair)
+ next-pair nil))
+ (while (and (not chunk-done)
+ (setq item (pop xrefs)))
+ (save-excursion
+ (let* ((loc (xref-item-location item))
+ (beg (xref-location-marker loc))
+ (end (move-marker (make-marker)
+ (+ beg (xref-match-length item))
+ (marker-buffer beg))))
+ (let ((pair (cons beg end)))
+ (push pair all-pairs)
+ ;; Perform sanity check first.
+ (xref--goto-location loc)
+ (if (xref--outdated-p item)
+ (message "Search result out of date, skipping")
+ (cond
+ ((null file-buf)
+ (setq file-buf (marker-buffer beg))
+ (push pair pairs))
+ ((equal file-buf (marker-buffer beg))
+ (push pair pairs))
+ (t
+ (setq chunk-done t
+ next-pair pair))))))))
+ (cons file-buf (nreverse pairs))))
+ (:cleanup
+ (dolist (pair all-pairs)
+ (move-marker (car pair) nil)
+ (move-marker (cdr pair) nil)))))))
+
+(defun xref--outdated-p (item)
+ "Check that the match location at current position is up-to-date.
+ITEMS is an xref item which "
+ ;; FIXME: The check should most likely be a generic function instead
+ ;; of the assumption that all matches' summaries relate to the
+ ;; buffer text in a particular way.
+ (let* ((summary (xref-item-summary item))
+ ;; Sometimes buffer contents include ^M, and sometimes Grep
+ ;; output includes it, and they don't always match.
+ (strip (lambda (s) (if (string-match "\r\\'" s)
+ (substring-no-properties s 0 -1)
+ s)))
+ (stripped-summary (funcall strip summary))
+ (lendpos (line-end-position))
+ (check (lambda ()
+ (let ((comparison-end
+ (+ (point) (length stripped-summary))))
+ (and (>= lendpos comparison-end)
+ (equal stripped-summary
+ (buffer-substring-no-properties
+ (point) comparison-end)))))))
+ (not
+ (or
+ ;; Either summary contains match text and after
+ ;; (2nd+ match on the line)...
+ (funcall check)
+ ;; ...or it starts at bol, includes the match and after.
+ (and (< (point) (+ (line-beginning-position)
+ (length stripped-summary)))
+ (save-excursion
+ (forward-line 0)
+ (funcall check)))))))
+
+;; FIXME: Write a nicer UI.
+(defun xref--query-replace-1 (from to iter)
+ (let* ((query-replace-lazy-highlight nil)
+ (continue t)
+ did-it-once buf-pairs pairs
+ current-beg current-end
+ ;; Counteract the "do the next match now" hack in
+ ;; `perform-replace'. And still, it'll report that those
+ ;; matches were "filtered out" at the end.
+ (isearch-filter-predicate
+ (lambda (beg end)
+ (and current-beg
+ (>= beg current-beg)
+ (<= end current-end))))
+ (replace-re-search-function
+ (lambda (from &optional _bound noerror)
+ (let (found pair)
+ (while (and (not found) pairs)
+ (setq pair (pop pairs)
+ current-beg (car pair)
+ current-end (cdr pair))
+ (goto-char current-beg)
+ (when (re-search-forward from current-end noerror)
+ (setq found t)))
+ found))))
+ (while (and continue (setq buf-pairs (funcall iter :next)))
+ (if did-it-once
+ ;; Reuse the same window for subsequent buffers.
+ (switch-to-buffer (car buf-pairs))
+ (xref--with-dedicated-window
+ (pop-to-buffer (car buf-pairs)))
+ (setq did-it-once t))
+ (setq pairs (cdr buf-pairs))
+ (setq continue
+ (perform-replace from to t t nil nil multi-query-replace-map)))
+ (unless did-it-once (user-error "No suitable matches here"))
+ (when (and continue (not buf-pairs))
+ (message "All results processed"))))
+
+(defvar xref--xref-buffer-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "n") #'xref-next-line)
+ (define-key map (kbd "p") #'xref-prev-line)
+ (define-key map (kbd "N") #'xref-next-group)
+ (define-key map (kbd "P") #'xref-prev-group)
+ (define-key map (kbd "r") #'xref-query-replace-in-results)
+ (define-key map (kbd "RET") #'xref-goto-xref)
+ (define-key map (kbd "TAB") #'xref-quit-and-goto-xref)
+ (define-key map (kbd "C-o") #'xref-show-location-at-point)
+ ;; suggested by Johan Claesson "to further reduce finger movement":
+ (define-key map (kbd ".") #'xref-next-line)
+ (define-key map (kbd ",") #'xref-prev-line)
+ (define-key map (kbd "g") #'xref-revert-buffer)
+ (define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack)
+ map))
+
+(define-derived-mode xref--xref-buffer-mode special-mode "XREF"
+ "Mode for displaying cross-references."
+ (setq buffer-read-only t)
+ (setq next-error-function #'xref--next-error-function)
+ (setq next-error-last-buffer (current-buffer))
+ (setq imenu-prev-index-position-function
+ #'xref--imenu-prev-index-position)
+ (setq imenu-extract-index-name-function
+ #'xref--imenu-extract-index-name))
+
+(defvar xref--transient-buffer-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "RET") #'xref-quit-and-goto-xref)
+ (set-keymap-parent map xref--xref-buffer-mode-map)
+ map))
+
+(define-derived-mode xref--transient-buffer-mode
+ xref--xref-buffer-mode
+ "XREF Transient")
+
+(defun xref--imenu-prev-index-position ()
+ "Move point to previous line in `xref' buffer.
+This function is used as a value for
+`imenu-prev-index-position-function'."
+ (if (bobp)
+ nil
+ (xref--search-property 'xref-group t)))
+
+(defun xref--imenu-extract-index-name ()
+ "Return imenu name for line at point.
+This function is used as a value for
+`imenu-extract-index-name-function'. Point should be at the
+beginning of the line."
+ (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position)))
+
+(defun xref--next-error-function (n reset?)
+ (when reset?
+ (goto-char (point-min)))
+ (let ((backward (< n 0))
+ (n (abs n))
+ (xref nil))
+ (if (= n 0)
+ (setq xref (get-text-property (point) 'xref-item))
+ (dotimes (_ n)
+ (setq xref (xref--search-property 'xref-item backward))))
+ (cond (xref
+ ;; Save the current position (when the buffer is visible,
+ ;; it gets reset to that window's point from time to time).
+ (let ((win (get-buffer-window (current-buffer))))
+ (and win (set-window-point win (point))))
+ (xref--show-location (xref-item-location xref) t))
+ (t
+ (error "No %s xref" (if backward "previous" "next"))))))
+
+(defvar xref--button-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mouse-1] #'xref-goto-xref)
+ (define-key map [mouse-2] #'xref--mouse-2)
+ map))
+
+(defun xref--mouse-2 (event)
+ "Move point to the button and show the xref definition."
+ (interactive "e")
+ (mouse-set-point event)
+ (forward-line 0)
+ (or (get-text-property (point) 'xref-item)
+ (xref--search-property 'xref-item))
+ (xref-show-location-at-point))
+
+(defun xref--insert-xrefs (xref-alist)
+ "Insert XREF-ALIST in the current-buffer.
+XREF-ALIST is of the form ((GROUP . (XREF ...)) ...), where
+GROUP is a string for decoration purposes and XREF is an
+`xref-item' object."
+ (require 'compile) ; For the compilation faces.
+ (cl-loop for ((group . xrefs) . more1) on xref-alist
+ for max-line-width =
+ (cl-loop for xref in xrefs
+ maximize (let ((line (xref-location-line
+ (oref xref location))))
+ (length (and line (format "%d" line)))))
+ for line-format = (and max-line-width
+ (format "%%%dd: " max-line-width))
+ with prev-group = nil
+ with prev-line = nil
+ do
+ (xref--insert-propertized '(face xref-file-header xref-group t)
+ group "\n")
+ (cl-loop for (xref . more2) on xrefs do
+ (with-slots (summary location) xref
+ (let* ((line (xref-location-line location))
+ (prefix
+ (cond
+ ((not line) " ")
+ ((equal line prev-line) "")
+ (t (propertize (format line-format line)
+ 'face 'xref-line-number)))))
+ ;; Render multiple matches on the same line, together.
+ (when (and (equal prev-group group)
+ (not (equal prev-line line)))
+ (insert "\n"))
+ (xref--insert-propertized
+ (list 'xref-item xref
+ 'mouse-face 'highlight
+ 'keymap xref--button-map
+ 'help-echo
+ (concat "mouse-2: display in another window, "
+ "RET or mouse-1: follow reference"))
+ prefix summary)
+ (setq prev-line line
+ prev-group group))))
+ (insert "\n"))
+ (run-hooks 'xref-after-update-hook))
+
+(defun xref--analyze (xrefs)
+ "Find common filenames in XREFS.
+Return an alist of the form ((FILENAME . (XREF ...)) ...)."
+ (xref--alistify xrefs
+ (lambda (x)
+ (xref-location-group (xref-item-location x)))
+ #'equal))
+
+(defun xref--show-xref-buffer (fetcher alist)
+ (cl-assert (functionp fetcher))
+ (let* ((xrefs
+ (or
+ (assoc-default 'fetched-xrefs alist)
+ (funcall fetcher)))
+ (xref-alist (xref--analyze xrefs))
+ (dd default-directory))
+ (with-current-buffer (get-buffer-create xref-buffer-name)
+ (setq default-directory dd)
+ (xref--xref-buffer-mode)
+ (xref--show-common-initialize xref-alist fetcher alist)
+ (pop-to-buffer (current-buffer))
+ (current-buffer))))
+
+(defun xref--project-root (project)
+ (if (fboundp 'project-root)
+ (project-root project)
+ (with-no-warnings
+ (car (project-roots project)))))
+
+(defun xref--show-common-initialize (xref-alist fetcher alist)
+ (setq buffer-undo-list nil)
+ (let ((inhibit-read-only t)
+ (buffer-undo-list t))
+ (erase-buffer)
+ (xref--insert-xrefs xref-alist)
+ (goto-char (point-min))
+ (setq xref--original-window (assoc-default 'window alist)
+ xref--original-window-intent (assoc-default 'display-action alist))
+ (setq xref--fetcher fetcher)))
+
+(defun xref-revert-buffer ()
+ "Refresh the search results in the current buffer."
+ (interactive)
+ (let ((inhibit-read-only t)
+ (buffer-undo-list t))
+ (save-excursion
+ (condition-case err
+ (let ((alist (xref--analyze (funcall xref--fetcher))))
+ (erase-buffer)
+ (xref--insert-xrefs alist))
+ (user-error
+ (erase-buffer)
+ (insert
+ (propertize
+ (error-message-string err)
+ 'face 'error)))))))
+
+(defun xref-show-definitions-buffer (fetcher alist)
+ "Show the definitions list in a regular window.
+
+When only one definition found, jump to it right away instead."
+ (let ((xrefs (funcall fetcher)))
+ (cond
+ ((not (cdr xrefs))
+ (xref-pop-to-location (car xrefs)
+ (assoc-default 'display-action alist)))
+ (t
+ (xref--show-xref-buffer fetcher
+ (cons (cons 'fetched-xrefs xrefs)
+ alist))))))
+
+(define-obsolete-function-alias
+ 'xref--show-defs-buffer #'xref-show-definitions-buffer "28.1")
+
+(defun xref-show-definitions-buffer-at-bottom (fetcher alist)
+ "Show the definitions list in a window at the bottom.
+
+When there is more than one definition, split the selected window
+and show the list in a small window at the bottom. And use a
+local keymap that binds `RET' to `xref-quit-and-goto-xref'."
+ (let* ((xrefs (funcall fetcher))
+ (dd default-directory)
+ ;; XXX: Make percentage customizable maybe?
+ (max-height (/ (window-height) 2))
+ (size-fun (lambda (window)
+ (fit-window-to-buffer window max-height))))
+ (cond
+ ((not (cdr xrefs))
+ (xref-pop-to-location (car xrefs)
+ (assoc-default 'display-action alist)))
+ (t
+ (with-current-buffer (get-buffer-create xref-buffer-name)
+ (setq default-directory dd)
+ (xref--transient-buffer-mode)
+ (xref--show-common-initialize (xref--analyze xrefs) fetcher alist)
+ (pop-to-buffer (current-buffer)
+ `(display-buffer-in-direction . ((direction . below)
+ (window-height . ,size-fun))))
+ (current-buffer))))))
+
+(define-obsolete-function-alias 'xref--show-defs-buffer-at-bottom
+ #'xref-show-definitions-buffer-at-bottom "28.1")
+
+(defun xref-show-definitions-completing-read (fetcher alist)
+ "Let the user choose the target definition with completion.
+
+When there is more than one definition, let the user choose
+between them by typing in the minibuffer with completion."
+ (let* ((xrefs (funcall fetcher))
+ (xref-alist (xref--analyze xrefs))
+ xref-alist-with-line-info
+ xref
+ (group-prefix-length
+ ;; FIXME: Groups are not always file names, but they often
+ ;; are. At least this shouldn't make the other kinds of
+ ;; groups look worse.
+ (let ((common-prefix (try-completion "" xref-alist)))
+ (if (> (length common-prefix) 0)
+ (length (file-name-directory common-prefix))
+ 0))))
+
+ (cl-loop for ((group . xrefs) . more1) on xref-alist
+ do
+ (cl-loop for (xref . more2) on xrefs do
+ (with-slots (summary location) xref
+ (let* ((line (xref-location-line location))
+ (line-fmt
+ (if line
+ (format #("%d:" 0 2 (face xref-line-number))
+ line)
+ ""))
+ (group-fmt
+ (propertize
+ (substring group group-prefix-length)
+ 'face 'xref-file-header))
+ (candidate
+ (format "%s:%s%s" group-fmt line-fmt summary)))
+ (push (cons candidate xref) xref-alist-with-line-info)))))
+
+ (setq xref (if (not (cdr xrefs))
+ (car xrefs)
+ (let* ((collection (reverse xref-alist-with-line-info))
+ (ctable
+ (lambda (string pred action)
+ (cond
+ ((eq action 'metadata)
+ '(metadata . ((category . xref-location))))
+ (t
+ (complete-with-action action collection string pred)))))
+ (def (caar collection)))
+ (cdr (assoc (completing-read "Choose definition: "
+ ctable nil t
+ nil nil
+ def)
+ collection)))))
+
+ (xref-pop-to-location xref (assoc-default 'display-action alist))))
+
+;; TODO: Can delete this alias before Emacs 28's release.
+(define-obsolete-function-alias
+ 'xref--show-defs-minibuffer #'xref-show-definitions-completing-read "28.1")
+
+
+(defcustom xref-show-xrefs-function 'xref--show-xref-buffer
+ "Function to display a list of search results.
+
+It should accept two arguments: FETCHER and ALIST.
+
+FETCHER is a function of no arguments that returns a list of xref
+values. It must not depend on the current buffer or selected
+window.
+
+ALIST can include, but limited to, the following keys:
+
+WINDOW for the window that was selected before the current
+command was called.
+
+DISPLAY-ACTION indicates where the target location should be
+displayed. The possible values are nil, `window' meaning the
+other window, or `frame' meaning the other frame."
+ :type 'function)
+
+(defcustom xref-show-definitions-function 'xref-show-definitions-buffer
+ "Function to handle the definition search results.
+
+Accepts the same arguments as `xref-show-xrefs-function'.
+
+Generally, it is expected to jump to the definition if there's
+only one, and otherwise provide some way to choose among the
+definitions."
+ :type '(choice
+ (const :tag "Show a regular list of locations"
+ xref-show-definitions-buffer)
+ (const :tag "Show a \"transient\" list at the bottom of the window"
+ xref-show-definitions-buffer-at-bottom)
+ (const :tag "Choose the definition with completion"
+ xref-show-definitions-completing-read)
+ (function :tag "Custom function")))
+
+(defvar xref--read-identifier-history nil)
+
+(defvar xref--read-pattern-history nil)
+
+(defun xref--show-xrefs (fetcher display-action &optional _always-show-list)
+ (xref--push-markers)
+ (unless (functionp fetcher)
+ ;; Old convention.
+ (let ((xrefs fetcher))
+ (setq fetcher
+ (lambda ()
+ (if (eq xrefs 'called-already)
+ (user-error "Refresh is not supported")
+ (prog1
+ xrefs
+ (setq xrefs 'called-already)))))))
+ (funcall xref-show-xrefs-function fetcher
+ `((window . ,(selected-window))
+ (display-action . ,display-action))))
+
+(defun xref--show-defs (xrefs display-action)
+ (xref--push-markers)
+ (funcall xref-show-definitions-function xrefs
+ `((window . ,(selected-window))
+ (display-action . ,display-action))))
+
+(defun xref--push-markers ()
+ (unless (region-active-p) (push-mark nil t))
+ (xref-push-marker-stack))
+
+(defun xref--prompt-p (command)
+ (or (eq xref-prompt-for-identifier t)
+ (if (eq (car xref-prompt-for-identifier) 'not)
+ (not (memq command (cdr xref-prompt-for-identifier)))
+ (memq command xref-prompt-for-identifier))))
+
+(defun xref--read-identifier (prompt)
+ "Return the identifier at point or read it from the minibuffer."
+ (let* ((backend (xref-find-backend))
+ (def (xref-backend-identifier-at-point backend))
+ (completion-ignore-case
+ (xref-backend-identifier-completion-ignore-case backend)))
+ (cond ((or current-prefix-arg
+ (not def)
+ (xref--prompt-p this-command))
+ (let ((id
+ (completing-read
+ (if def
+ (format "%s (default %s): "
+ (substring prompt 0 (string-match
+ "[ :]+\\'" prompt))
+ def)
+ prompt)
+ (xref-backend-identifier-completion-table backend)
+ nil nil nil
+ 'xref--read-identifier-history def)))
+ (if (equal id "")
+ (or def (user-error "There is no default identifier"))
+ id)))
+ (t def))))
+
+
+;;; Commands
+
+(defun xref--find-xrefs (input kind arg display-action)
+ (xref--show-xrefs
+ (xref--create-fetcher input kind arg)
+ display-action))
+
+(defun xref--find-definitions (id display-action)
+ (xref--show-defs
+ (xref--create-fetcher id 'definitions id)
+ display-action))
+
+(defun xref--create-fetcher (input kind arg)
+ "Return an xref list fetcher function.
+
+It revisits the saved position and delegates the finding logic to
+the xref backend method indicated by KIND and passes ARG to it."
+ (let* ((orig-buffer (current-buffer))
+ (orig-position (point))
+ (backend (xref-find-backend))
+ (method (intern (format "xref-backend-%s" kind))))
+ (lambda ()
+ (save-excursion
+ ;; Xref methods are generally allowed to depend on the text
+ ;; around point, not just on their explicit arguments.
+ ;;
+ ;; There is only so much we can do, however, to recreate that
+ ;; context, given that the user is free to change the buffer
+ ;; contents freely in the meantime.
+ (when (buffer-live-p orig-buffer)
+ (set-buffer orig-buffer)
+ (ignore-errors (goto-char orig-position)))
+ (let ((xrefs (funcall method backend arg)))
+ (unless xrefs
+ (xref--not-found-error kind input))
+ xrefs)))))
+
+(defun xref--not-found-error (kind input)
+ (user-error "No %s found for: %s" (symbol-name kind) input))
+
+;;;###autoload
+(defun xref-find-definitions (identifier)
+ "Find the definition of the identifier at point.
+With prefix argument or when there's no identifier at point,
+prompt for it.
+
+If sufficient information is available to determine a unique
+definition for IDENTIFIER, display it in the selected window.
+Otherwise, display the list of the possible definitions in a
+buffer where the user can select from the list."
+ (interactive (list (xref--read-identifier "Find definitions of: ")))
+ (xref--find-definitions identifier nil))
+
+;;;###autoload
+(defun xref-find-definitions-other-window (identifier)
+ "Like `xref-find-definitions' but switch to the other window."
+ (interactive (list (xref--read-identifier "Find definitions of: ")))
+ (xref--find-definitions identifier 'window))
+
+;;;###autoload
+(defun xref-find-definitions-other-frame (identifier)
+ "Like `xref-find-definitions' but switch to the other frame."
+ (interactive (list (xref--read-identifier "Find definitions of: ")))
+ (xref--find-definitions identifier 'frame))
+
+;;;###autoload
+(defun xref-find-references (identifier)
+ "Find references to the identifier at point.
+This command might prompt for the identifier as needed, perhaps
+offering the symbol at point as the default.
+With prefix argument, or if `xref-prompt-for-identifier' is t,
+always prompt for the identifier. If `xref-prompt-for-identifier'
+is nil, prompt only if there's no usable symbol at point."
+ (interactive (list (xref--read-identifier "Find references of: ")))
+ (xref--find-xrefs identifier 'references identifier nil))
+
+;;;###autoload
+(defun xref-find-definitions-at-mouse (event)
+ "Find the definition of identifier at or around mouse click.
+This command is intended to be bound to a mouse event."
+ (interactive "e")
+ (let ((identifier
+ (save-excursion
+ (mouse-set-point event)
+ (xref-backend-identifier-at-point (xref-find-backend)))))
+ (if identifier
+ (xref-find-definitions identifier)
+ (user-error "No identifier here"))))
+
+(declare-function apropos-parse-pattern "apropos" (pattern))
+
+;;;###autoload
+(defun xref-find-apropos (pattern)
+ "Find all meaningful symbols that match PATTERN.
+The argument has the same meaning as in `apropos'."
+ (interactive (list (read-string
+ "Search for pattern (word list or regexp): "
+ nil 'xref--read-pattern-history)))
+ (require 'apropos)
+ (let* ((newpat
+ (if (and (version< emacs-version "28.0.50")
+ (memq (xref-find-backend) '(elisp etags)))
+ ;; Handle backends in older Emacs.
+ (xref-apropos-regexp pattern)
+ ;; Delegate pattern handling to the backend fully.
+ ;; The old way didn't work for "external" backends.
+ pattern)))
+ (xref--find-xrefs pattern 'apropos newpat nil)))
+
+(defun xref-apropos-regexp (pattern)
+ "Return an Emacs regexp from PATTERN similar to `apropos'."
+ (apropos-parse-pattern
+ (if (string-equal (regexp-quote pattern) pattern)
+ ;; Split into words
+ (or (split-string pattern "[ \t]+" t)
+ (user-error "No word list given"))
+ pattern)))
+
+
+;;; Key bindings
+
+;;;###autoload (define-key esc-map "." #'xref-find-definitions)
+;;;###autoload (define-key esc-map "," #'xref-pop-marker-stack)
+;;;###autoload (define-key esc-map "?" #'xref-find-references)
+;;;###autoload (define-key esc-map [?\C-.] #'xref-find-apropos)
+;;;###autoload (define-key ctl-x-4-map "." #'xref-find-definitions-other-window)
+;;;###autoload (define-key ctl-x-5-map "." #'xref-find-definitions-other-frame)
+
+
+;;; Helper functions
+
+(defvar xref-etags-mode--saved nil)
+
+(define-minor-mode xref-etags-mode
+ "Minor mode to make xref use etags again.
+
+Certain major modes install their own mechanisms for listing
+identifiers and navigation. Turn this on to undo those settings
+and just use etags."
+ :lighter ""
+ (if xref-etags-mode
+ (progn
+ (setq xref-etags-mode--saved xref-backend-functions)
+ (kill-local-variable 'xref-backend-functions))
+ (setq-local xref-backend-functions xref-etags-mode--saved)))
+
+(declare-function semantic-symref-instantiate "semantic/symref")
+(declare-function semantic-symref-perform-search "semantic/symref")
+(declare-function grep-expand-template "grep")
+(defvar ede-minor-mode) ;; ede.el
+
+;;;###autoload
+(defun xref-references-in-directory (symbol dir)
+ "Find all references to SYMBOL in directory DIR.
+Return a list of xref values.
+
+This function uses the Semantic Symbol Reference API, see
+`semantic-symref-tool-alist' for details on which tools are used,
+and when."
+ (cl-assert (directory-name-p dir))
+ (require 'semantic/symref)
+ (defvar semantic-symref-tool)
+
+ ;; Some symref backends use `ede-project-root-directory' as the root
+ ;; directory for the search, rather than `default-directory'. Since
+ ;; the caller has specified `dir', we bind `ede-minor-mode' to nil
+ ;; to force the backend to use `default-directory'.
+ (let* ((ede-minor-mode nil)
+ (default-directory dir)
+ ;; FIXME: Remove CScope and Global from the recognized tools?
+ ;; The current implementations interpret the symbol search as
+ ;; "find all calls to the given function", but not function
+ ;; definition. And they return nothing when passed a variable
+ ;; name, even a global one.
+ (semantic-symref-tool 'detect)
+ (case-fold-search nil)
+ (inst (semantic-symref-instantiate :searchfor symbol
+ :searchtype 'symbol
+ :searchscope 'subdirs
+ :resulttype 'line-and-text)))
+ (xref--convert-hits (semantic-symref-perform-search inst)
+ (format "\\_<%s\\_>" (regexp-quote symbol)))))
+
+(define-obsolete-function-alias
+ 'xref-collect-references
+ #'xref-references-in-directory
+ "27.1")
+
+;;;###autoload
+(defun xref-matches-in-directory (regexp files dir ignores)
+ "Find all matches for REGEXP in directory DIR.
+Return a list of xref values.
+Only files matching some of FILES and none of IGNORES are searched.
+FILES is a string with glob patterns separated by spaces.
+IGNORES is a list of glob patterns for files to ignore."
+ ;; DIR can also be a regular file for now; let's not advertise that.
+ (grep-compute-defaults)
+ (defvar grep-find-template)
+ (defvar grep-highlight-matches)
+ (pcase-let*
+ ((grep-find-template (replace-regexp-in-string "<C>" "<C> -E"
+ grep-find-template t t))
+ (grep-highlight-matches nil)
+ ;; TODO: Sanitize the regexp to remove Emacs-specific terms,
+ ;; so that Grep can search for the "relaxed" version. Can we
+ ;; do that reliably enough, without creating false negatives?
+ (command (xref--rgrep-command (xref--regexp-to-extended regexp)
+ files
+ (file-name-as-directory
+ (file-name-unquote
+ (file-local-name (expand-file-name dir))))
+ ignores))
+ (def default-directory)
+ (buf (get-buffer-create " *xref-grep*"))
+ (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
+ (status nil)
+ (hits nil))
+ (with-current-buffer buf
+ (erase-buffer)
+ (setq default-directory def)
+ (setq status
+ (process-file-shell-command command nil t))
+ (goto-char (point-min))
+ ;; Can't use the exit status: Grep exits with 1 to mean "no
+ ;; matches found". Find exits with 1 if any of the invocations
+ ;; exit with non-zero. "No matches" and "Grep program not found"
+ ;; are all the same to it.
+ (when (and (/= (point-min) (point-max))
+ (not (looking-at grep-re)))
+ (user-error "Search failed with status %d: %s" status (buffer-string)))
+ (while (re-search-forward grep-re nil t)
+ (push (list (string-to-number (match-string line-group))
+ (match-string file-group)
+ (buffer-substring-no-properties (point) (line-end-position)))
+ hits)))
+ (xref--convert-hits (nreverse hits) regexp)))
+
+(define-obsolete-function-alias
+ 'xref-collect-matches
+ #'xref-matches-in-directory
+ "27.1")
+
+(declare-function tramp-tramp-file-p "tramp")
+(declare-function tramp-file-local-name "tramp")
+
+;; TODO: Experiment with 'xargs -P4' (or any other number).
+;; This speeds up either command, even more than rg's '-j4' does.
+;; Ripgrep gets jumbled output, though, even with --line-buffered.
+;; But Grep seems to be stable. Even without --line-buffered.
+(defcustom xref-search-program-alist
+ '((grep
+ .
+ ;; '-s' because 'git ls-files' can output broken symlinks.
+ "xargs -0 grep <C> -snHE -e <R>")
+ (ripgrep
+ .
+ ;; Note: by default, ripgrep's output order is non-deterministic
+ ;; (https://github.com/BurntSushi/ripgrep/issues/152)
+ ;; because it does the search in parallel. You can use the template
+ ;; without the '| sort ...' part if GNU sort is not available on
+ ;; your system and/or stable ordering is not important to you.
+ ;; Note#2: '!*/' is there to filter out dirs (e.g. submodules).
+ "xargs -0 rg <C> -nH --no-messages -g '!*/' -e <R> | sort -t: -k1,1 -k2n,2"
+ ))
+ "Associative list mapping program identifiers to command templates.
+
+Program identifier should be a symbol, named after the search program.
+
+The command template must be a shell command (or usually a
+pipeline) that will search the files based on the list of file
+names that is piped from stdin, separated by null characters.
+The template should have the following fields:
+
+ <C> for extra arguments such as -i and --color
+ <R> for the regexp itself (in Extended format)"
+ :type '(repeat
+ (cons (symbol :tag "Program identifier")
+ (string :tag "Command template")))
+ :version "28.1"
+ :package-version '(xref . "1.0.4"))
+
+(defcustom xref-search-program 'grep
+ "The program to use for regexp search inside files.
+
+This must reference a corresponding entry in `xref-search-program-alist'."
+ :type `(choice
+ (const :tag "Use Grep" grep)
+ (const :tag "Use ripgrep" ripgrep)
+ (symbol :tag "User defined"))
+ :version "28.1"
+ :package-version '(xref . "1.0.4"))
+
+;;;###autoload
+(defun xref-matches-in-files (regexp files)
+ "Find all matches for REGEXP in FILES.
+Return a list of xref values.
+FILES must be a list of absolute file names."
+ (cl-assert (consp files))
+ (require 'grep)
+ (defvar grep-highlight-matches)
+ (pcase-let*
+ ((output (get-buffer-create " *project grep output*"))
+ (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
+ (status nil)
+ (hits nil)
+ ;; Support for remote files. The assumption is that, if the
+ ;; first file is remote, they all are, and on the same host.
+ (dir (file-name-directory (car files)))
+ (remote-id (file-remote-p dir))
+ ;; The 'auto' default would be fine too, but ripgrep can't handle
+ ;; the options we pass in that case.
+ (grep-highlight-matches nil)
+ (command (grep-expand-template (cdr
+ (or
+ (assoc
+ xref-search-program
+ xref-search-program-alist)
+ (user-error "Unknown search program `%s'"
+ xref-search-program)))
+ (xref--regexp-to-extended regexp))))
+ (when remote-id
+ (require 'tramp)
+ (setq files (mapcar
+ (if (tramp-tramp-file-p dir)
+ #'tramp-file-local-name
+ #'file-local-name)
+ files)))
+ (when (file-name-quoted-p (car files))
+ (setq files (mapcar #'file-name-unquote files)))
+ (with-current-buffer output
+ (erase-buffer)
+ (with-temp-buffer
+ (insert (mapconcat #'identity files "\0"))
+ (setq default-directory dir)
+ (setq status
+ (xref--process-file-region (point-min)
+ (point-max)
+ shell-file-name
+ output
+ nil
+ shell-command-switch
+ command)))
+ (goto-char (point-min))
+ (when (and (/= (point-min) (point-max))
+ (not (looking-at grep-re))
+ ;; TODO: Show these matches as well somehow?
+ (not (looking-at "Binary file .* matches")))
+ (user-error "Search failed with status %d: %s" status
+ (buffer-substring (point-min) (line-end-position))))
+ (while (re-search-forward grep-re nil t)
+ (push (list (string-to-number (match-string line-group))
+ (match-string file-group)
+ (buffer-substring-no-properties (point) (line-end-position)))
+ hits)))
+ (xref--convert-hits (nreverse hits) regexp)))
+
+(defun xref--process-file-region ( start end program
+ &optional buffer display
+ &rest args)
+ ;; FIXME: This branching shouldn't be necessary, but
+ ;; call-process-region *is* measurably faster, even for a program
+ ;; doing some actual work (for a period of time). Even though
+ ;; call-process-region also creates a temp file internally
+ ;; (https://lists.gnu.org/archive/html/emacs-devel/2019-01/msg00211.html).
+ (if (not (file-remote-p default-directory))
+ (apply #'call-process-region
+ start end program nil buffer display args)
+ (let ((infile (make-temp-file "ppfr")))
+ (unwind-protect
+ (progn
+ (write-region start end infile nil 'silent)
+ (apply #'process-file program infile buffer display args))
+ (delete-file infile)))))
+
+(defun xref--rgrep-command (regexp files dir ignores)
+ (require 'find-dired) ; for `find-name-arg'
+ (defvar grep-find-template)
+ (defvar find-name-arg)
+ ;; `shell-quote-argument' quotes the tilde as well.
+ (cl-assert (not (string-match-p "\\`~" dir)))
+ (grep-expand-template
+ grep-find-template
+ regexp
+ (concat (shell-quote-argument "(")
+ " " find-name-arg " "
+ (mapconcat
+ #'shell-quote-argument
+ (split-string files)
+ (concat " -o " find-name-arg " "))
+ " "
+ (shell-quote-argument ")"))
+ (shell-quote-argument dir)
+ (xref--find-ignores-arguments ignores dir)))
+
+(defun xref--find-ignores-arguments (ignores dir)
+ "Convert IGNORES and DIR to a list of arguments for 'find'.
+IGNORES is a list of glob patterns. DIR is an absolute
+directory, used as the root of the ignore globs."
+ (cl-assert (not (string-match-p "\\`~" dir)))
+ (if (not ignores)
+ ""
+ (concat
+ (shell-quote-argument "(")
+ " -path "
+ (mapconcat
+ (lambda (ignore)
+ (when (string-match-p "/\\'" ignore)
+ (setq ignore (concat ignore "*")))
+ (shell-quote-argument (if (string-match "\\`\\./" ignore)
+ (replace-match dir t t ignore)
+ (if (string-prefix-p "*" ignore)
+ ignore
+ (concat "*/" ignore)))))
+ ignores
+ " -o -path ")
+ " "
+ (shell-quote-argument ")")
+ " -prune -o ")))
+
+(defun xref--regexp-to-extended (str)
+ (replace-regexp-in-string
+ ;; FIXME: Add tests. Move to subr.el, make a public function.
+ ;; Maybe error on Emacs-only constructs.
+ "\\(?:\\\\\\\\\\)*\\(?:\\\\[][]\\)?\\(?:\\[.+?\\]\\|\\(\\\\?[(){}|]\\)\\)"
+ (lambda (str)
+ (cond
+ ((not (match-beginning 1))
+ str)
+ ((eq (length (match-string 1 str)) 2)
+ (concat (substring str 0 (match-beginning 1))
+ (substring (match-string 1 str) 1 2)))
+ (t
+ (concat (substring str 0 (match-beginning 1))
+ "\\"
+ (match-string 1 str)))))
+ str t t))
+
+(defun xref--regexp-syntax-dependent-p (str)
+ "Return non-nil when STR depends on the buffer's syntax.
+Such as the current syntax table and the applied syntax properties."
+ (let ((case-fold-search nil))
+ (string-match-p (rx
+ (or string-start (not (in ?\\)))
+ (0+ (= 2 ?\\))
+ ?\\
+ (in ?b ?B ?< ?> ?w ?W ?_ ?s ?S))
+ str)))
+
+(defvar xref--last-file-buffer nil)
+(defvar xref--temp-buffer-file-name nil)
+
+(defun xref--convert-hits (hits regexp)
+ (let (xref--last-file-buffer
+ (tmp-buffer (generate-new-buffer " *xref-temp*")))
+ (unwind-protect
+ (mapcan (lambda (hit) (xref--collect-matches hit regexp tmp-buffer))
+ hits)
+ (kill-buffer tmp-buffer))))
+
+(defun xref--collect-matches (hit regexp tmp-buffer)
+ (pcase-let* ((`(,line ,file ,text) hit)
+ (remote-id (file-remote-p default-directory))
+ (file (and file (concat remote-id file)))
+ (buf (xref--find-file-buffer file))
+ (syntax-needed (xref--regexp-syntax-dependent-p regexp)))
+ (if buf
+ (with-current-buffer buf
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (xref--collect-matches-1 regexp file line
+ (line-beginning-position)
+ (line-end-position)
+ syntax-needed)))
+ ;; Using the temporary buffer is both a performance and a buffer
+ ;; management optimization.
+ (with-current-buffer tmp-buffer
+ (erase-buffer)
+ (when (and syntax-needed
+ (not (equal file xref--temp-buffer-file-name)))
+ (insert-file-contents file nil 0 200)
+ ;; Can't (setq-local delay-mode-hooks t) because of
+ ;; bug#23272, but the performance penalty seems minimal.
+ (let ((buffer-file-name file)
+ (inhibit-message t)
+ message-log-max)
+ (ignore-errors
+ (set-auto-mode t)))
+ (setq-local xref--temp-buffer-file-name file)
+ (setq-local inhibit-read-only t)
+ (erase-buffer))
+ (insert text)
+ (goto-char (point-min))
+ (xref--collect-matches-1 regexp file line
+ (point)
+ (point-max)
+ syntax-needed)))))
+
+(defun xref--collect-matches-1 (regexp file line line-beg line-end syntax-needed)
+ (let (match-pairs matches)
+ (when syntax-needed
+ (syntax-propertize line-end))
+ (while (and
+ ;; REGEXP might match an empty string. Or line.
+ (or (null match-pairs)
+ (> (point) line-beg))
+ (re-search-forward regexp line-end t))
+ (push (cons (match-beginning 0)
+ (match-end 0))
+ match-pairs))
+ (setq match-pairs (nreverse match-pairs))
+ (while match-pairs
+ (let* ((beg-end (pop match-pairs))
+ (beg-column (- (car beg-end) line-beg))
+ (end-column (- (cdr beg-end) line-beg))
+ (loc (xref-make-file-location file line beg-column))
+ (summary (buffer-substring (if matches (car beg-end) line-beg)
+ (if match-pairs
+ (caar match-pairs)
+ line-end))))
+ (when matches
+ (cl-decf beg-column (- (car beg-end) line-beg))
+ (cl-decf end-column (- (car beg-end) line-beg)))
+ (add-face-text-property beg-column end-column 'xref-match
+ t summary)
+ (push (xref-make-match summary loc (- end-column beg-column))
+ matches)))
+ (nreverse matches)))
+
+(defun xref--find-file-buffer (file)
+ (unless (equal (car xref--last-file-buffer) file)
+ (setq xref--last-file-buffer
+ ;; `find-buffer-visiting' is considerably slower,
+ ;; especially on remote files.
+ (cons file (get-file-buffer file))))
+ (cdr xref--last-file-buffer))
+
+(provide 'xref)
+
+;;; xref.el ends here
diff --git a/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-autoloads.el b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-autoloads.el
new file mode 100644
index 0000000..4d97511
--- /dev/null
+++ b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-autoloads.el
@@ -0,0 +1,82 @@
+;;; xterm-color-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "xterm-color" "xterm-color.el" (0 0 0 0))
+;;; Generated autoloads from xterm-color.el
+
+(autoload 'xterm-color-filter-strip "xterm-color" "\
+Translate ANSI color sequences in STRING into text properties.
+Return new STRING with text properties applied.
+
+In order to get maximum performance, this function strips text properties
+if they are present in STRING.
+
+\(fn STRING)" nil nil)
+
+(autoload 'xterm-color-filter "xterm-color" "\
+Translate ANSI color sequences in STRING into text properties.
+Return new STRING with text properties applied.
+
+This function checks if `xterm-color-preserve-properties' is non-nil
+and only calls `xterm-color-filter-strip' on substrings that do not
+have text properties applied (passing through the rest unmodified).
+Preserving properties in this fashion is not very robust as there may
+be situations where text properties are applied on ANSI data, which
+will desync the state machine.
+
+Preserving properties works ok with and is really meant for eshell.
+
+This can be inserted into `comint-preoutput-filter-functions'.
+
+\(fn STRING)" nil nil)
+
+(autoload 'xterm-color-256 "xterm-color" "\
+
+
+\(fn COLOR)" nil nil)
+
+(autoload 'xterm-color-colorize-buffer "xterm-color" "\
+Apply `xterm-color-filter' to current buffer, and replace its contents.
+Colors are applied using 'face, unless font-lock-mode is active, in
+which case 'font-lock-face is used. Operation with font-lock mode active
+is not recommended.
+
+If USE-OVERLAYS is non-nil, colors are applied to the buffer using overlays
+instead of text properties. A C-u prefix arg causes overlays to be used.
+
+\(fn &optional USE-OVERLAYS)" t nil)
+
+(autoload 'xterm-color-clear-cache "xterm-color" "\
+Clear xterm color face attribute cache.
+You may want to call this if you change `xterm-color-names' or
+`xterm-color-names-bright' at runtime and you want to see the changes
+take place in a pre-existing buffer that has had xterm-color initialized.
+
+Since the cache is buffer-local and created on-demand when needed, this has no
+effect when called from a buffer that does not have a cache." t nil)
+
+(autoload 'xterm-color-test "xterm-color" "\
+Create, display and render a new buffer containing ANSI control sequences." t nil)
+
+(autoload 'xterm-color-test-raw "xterm-color" "\
+Create and display a new buffer containing ANSI SGR control sequences.
+ANSI sequences are not processed. One can use a different Emacs package,
+such as ansi-color.el to do so. This is really meant to be used for easy
+comparisons/benchmarks with libraries that offer similar functionality." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xterm-color" '("+xterm-color--table-256+" "xterm-color-")))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; xterm-color-autoloads.el ends here
diff --git a/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-pkg.el b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-pkg.el
new file mode 100644
index 0000000..dfa6653
--- /dev/null
+++ b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color-pkg.el
@@ -0,0 +1,2 @@
+;;; Generated package description from xterm-color-20200605.2017/xterm-color.el -*- no-byte-compile: t -*-
+(define-package "xterm-color" "20200605.2017" "ANSI, XTERM 256 and Truecolor support" '((emacs "24.4")) :commit "1a4012854c69a5cdaeb5a73d2ad705011892fca3" :authors '(("xristos" . "xristos@sdf.org")) :maintainer '("xristos" . "xristos@sdf.org") :keywords '("faces") :url "https://github.com/atomontage/xterm-color")
diff --git a/emacs.d/elpa/xterm-color-20200605.2017/xterm-color.el b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color.el
new file mode 100644
index 0000000..e786513
--- /dev/null
+++ b/emacs.d/elpa/xterm-color-20200605.2017/xterm-color.el
@@ -0,0 +1,938 @@
+;;; xterm-color.el --- ANSI, XTERM 256 and Truecolor support -*- lexical-binding: t -*-
+
+;; Copyright (C) 2010-2020 xristos@sdf.org
+;; All rights reserved
+
+;; Modified: 2020-05-10
+;; Version: 2.0
+;; Package-Version: 20200605.2017
+;; Package-Commit: 1a4012854c69a5cdaeb5a73d2ad705011892fca3
+;; Author: xristos <xristos@sdf.org>
+;; URL: https://github.com/atomontage/xterm-color
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: faces
+
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions
+;; are met:
+;;
+;; * Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;;
+;; * Redistributions in binary form must reproduce the above
+;; copyright notice, this list of conditions and the following
+;; disclaimer in the documentation and/or other materials
+;; provided with the distribution.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+;; POSSIBILITY OF SUCH DAMAGE.
+
+;;; Commentary:
+;;
+;; Translate ANSI control sequences into text properties through state machine
+;; emulation. This provides a far more accurate, comprehensive result than
+;; `ansi-color.el' that is built-into Emacs, without compromising on performance.
+;;
+;; Please see README.org for documentation including example configurations.
+;;
+;;; Notes:
+;;
+;; Unsupported SGR attributes: 5 (slow blink), 6 (rapid blink), 8 (conceal),
+;; 10 (primary font), 11-19 (alternative font), 20 (fraktur), 21 (double underline),
+;; 25 (blink off), 29 (reveal), 52 (encircled), 60-65 (ideogram)
+;;
+;; Most of these can not be mapped to Emacs face properties. The rest may be
+;; supported in a future release.
+;;
+;; Supported SGR attributes: Look at `xterm-color--dispatch-SGR'.
+;; SGR attribute 1 is rendered as bright unless `xterm-color-use-bold-for-bright'
+;; is non-nil which will, if current font has a bold variant, switch to bold.
+;; SGR attributes 38 and 48 are supported in both their 256 color and truecolor
+;; (24-bit) variants.
+
+;;; Test:
+;;
+;; M-x xterm-color-test
+;;
+;; In shell or eshell:
+;;
+;; perl tests/xterm-colortest && perl tests/256colors2.pl
+;;
+;; printf "\x1b[0;1;3;4;35;51mThis is only a test\x1b[0m\n"
+;;
+;; Comparison with ansi-color.el:
+;;
+;; M-x xterm-color-test-raw then M-x xterm-color-colorize-buffer
+;;
+;; and contrast with
+;;
+;; M-x xterm-color-test-raw then M-: (ansi-color-apply-on-region (point-min) (point-max))
+;;
+;; Use `xterm-color--bench' for benchmarks during development.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'cl-lib)
+
+(defgroup xterm-color nil
+ "Translate ANSI control sequences to text properties."
+ :prefix "xterm-color-"
+ :group 'processes)
+
+
+;;;
+;;; CUSTOM
+;;;
+
+
+(defcustom xterm-color-debug nil
+ "If non-nil, print ANSI state machine debug information in *Messages*."
+ :type 'boolean
+ :group 'xterm-color)
+
+(defcustom xterm-color-use-bold-for-bright nil
+ "If non-nil, render bright foreground attribute as bold."
+ :type 'boolean
+ :group 'xterm-color)
+
+(defcustom xterm-color-names
+ ["#192033" ; black
+ "#A93F43" ; red
+ "#59963A" ; green
+ "#BE8A2D" ; yellow
+ "#4068A3" ; blue
+ "#7F60A7" ; magenta
+ "#4E9B9B" ; cyan
+ "#7E8A90"] ; white
+ "Default colors to use as regular ANSI colors."
+ :type '(vector string string string string string string string string)
+ :group 'xterm-color)
+
+(defcustom xterm-color-names-bright
+ ["#666666" ; black
+ "#EC6261" ; red
+ "#ADCF44" ; green
+ "#F0C649" ; yellow
+ "#63B4F6" ; blue
+ "#CB77F9" ; magenta
+ "#86D7DB" ; cyan
+ "#D3D2D1"] ; white
+ "Default colors to use as bright ANSI colors."
+ :type '(vector string string string string string string string string)
+ :group 'xterm-color)
+
+
+;;;
+;;; Buffer locals, used by state machine
+;;;
+
+
+(defvar-local xterm-color-preserve-properties nil
+ "If non-nil, preserve existing text properties on input about to be filtered.
+Effectively this skips ANSI control sequence processing for input parts
+that have text properties applied. This should be nil most of the time.
+It is really meant for and works ok with eshell.")
+
+(defvar-local xterm-color-render t
+ "If non-nil, render SGR attributes. Otherwise, discard them.
+The latter enables processing and filtering out ANSI control sequences,
+without applying them to the text.")
+
+(defvar-local xterm-color--current-fg nil)
+
+(defvar-local xterm-color--current-bg nil)
+
+(defvar-local xterm-color--char-list nil
+ "List of characters that the current ANSI color applies to.
+All characters are stored in reverse, LIFO, order.")
+
+(defvar-local xterm-color--CSI-list nil
+ "List of current ANSI CSI sequence bytes (characters).
+All characters are stored in reverse, LIFO, order.")
+
+(defvar-local xterm-color--state :char
+ "Current state of ANSI state machine.
+
+Can be one of :char, :set-char, :ansi-esc, :ansi-csi, :ansi-osc,
+:ansi-osc-esc.")
+
+(defvar-local xterm-color--attributes 0
+ "Bitvector that keeps track of state machine attributes.
+
+These are: bright, italic, underline, strike-through, inverse-color,
+frame, overline.")
+
+(defvar-local xterm-color--face-cache nil
+ "Cache for auto-generated face attributes.")
+
+(defvar-local xterm-color--truecolor-face-cache nil
+ "Cache for auto-generated face attributes.")
+
+
+;;;
+;;; Constants
+;;;
+
+
+(defconst +xterm-color--table-256+ [0 #x5f #x87 #xaf #xd7 #xff])
+
+
+;;;
+;;; Internal API
+;;;
+
+;; The face caching scheme requires an integer width of at least 56 bits
+;; to cache faces derived from truecolor (24-bit) ANSI sequences. Truecolor
+;; support is therefore disabled on e.g. machines with 32-bit integers.
+(defvar xterm-color--support-truecolor (>= (1+ (floor (log most-positive-fixnum 2)))
+ 59))
+
+(cl-defun xterm-color--string-properties (string)
+ (cl-loop
+ with pos = 0 and result do
+ (let ((next-pos (next-property-change pos string)))
+ (if next-pos
+ (progn
+ (push (list pos (text-properties-at pos string) (substring string pos next-pos)) result)
+ (setq pos next-pos))
+ (push (list pos (text-properties-at pos string) (substring string pos)) result)
+ (cl-return-from xterm-color--string-properties (nreverse result))))))
+
+(defun xterm-color--convert-text-properties-to-overlays (beg end)
+ "Transform face text properties between BEG and END, to equivalent overlays."
+ (save-excursion
+ (goto-char beg)
+ (let ((face-prop (if (or (get-text-property (point) 'font-lock-face)
+ (next-single-property-change (point) 'font-lock-face))
+ 'font-lock-face 'face)))
+ (while (< (point) end)
+ (let* ((pos (point))
+ (current-value (get-text-property pos face-prop))
+ (next-change (next-single-property-change pos face-prop nil end)))
+ (when current-value
+ (let ((ov (make-overlay pos next-change)))
+ (overlay-put ov face-prop current-value)
+ (overlay-put ov 'xterm-color t)))
+ (goto-char next-change)))
+ (remove-text-properties beg end (list 'xterm-color nil face-prop nil)))))
+
+(defun xterm-color--message (format-string &rest args)
+ "Call `message' with FORMAT-STRING and ARGS.
+Also see `xterm-color-debug'."
+ (when xterm-color-debug
+ (let ((message-truncate-lines t))
+ (message "xterm-color: %s" (apply #'format format-string args))
+ (message nil))))
+
+
+;;;
+;;; SGR state machine
+;;;
+
+
+(cl-defmacro xterm-color--with-SGR-constants (&body body)
+ (declare (indent defun))
+ `(cl-symbol-macrolet
+ ((+bright+ 1)
+ (+italic+ 2)
+ (+underline+ 4)
+ (+strike-through+ 8)
+ (+negative+ 16)
+ (+frame+ 32)
+ (+overline+ 64))
+ ,@body))
+
+(cl-defmacro xterm-color--create-SGR-table ((attrib SGR-list) &body body)
+ "Create an iteration/dispatch table based on provided rules that match SGR attributes.
+For each attribute in SGR-LIST, check to see if it matches a rule in BODY and
+evaluate the rule body if that is the case.
+
+ATTRIB must be a symbol that is bound to SGR-LIST attributes in BODY.
+SGR-LIST must be a list of SGR attributes (integers) in LIFO order.
+BODY must contain rules with each rule being a list of form:
+
+ (:match (condition &key (skip 1)) rule-body-form..)
+
+CONDITION must be a Lisp form which is evaluated as part of a COND
+condition clause. If it is an atom, it is rewritten to (eq CONDITION ATTRIB).
+Otherwise it is used as is. As per COND statement, if CONDITION evaluates
+to non-nil, rule body forms are evaluated as part of the body of the COND clause.
+
+SKIP, if given, must be an integer specifying the number of elements that
+should be skipped before the next iteration. The default is 1,
+going down SGR-LIST one element at a time."
+ (declare (indent defun))
+ `(xterm-color--with-SGR-constants
+ (cl-macrolet
+ ;; The following macros should be used in rule bodies
+ ((set-a! (attr) `(setq xterm-color--attributes
+ (logior xterm-color--attributes ,attr)))
+ (unset-a! (attr) `(setq xterm-color--attributes
+ (logand xterm-color--attributes
+ (logand #xff (lognot ,attr)))))
+
+ (set-f! (fg-color) `(setq xterm-color--current-fg ,fg-color))
+ (set-b! (bg-color) `(setq xterm-color--current-bg ,bg-color))
+
+ (set-truecolor! (r g b current-color)
+ ;; A single integer must be able to
+ ;; hold and distinguish between:
+ ;;
+ ;; - 24bit truecolor values
+ ;; - ANSI colors
+ ;; - XTerm 256 colors
+ ;;
+ ;; The following packing scheme achieves that.
+ `(setq ,current-color
+ (logior (ash r 25) (ash g 17) (ash b 9)
+ #x100)))
+
+ (reset! () `(setq xterm-color--current-fg nil
+ xterm-color--current-bg nil
+ xterm-color--attributes 0)))
+ (cl-loop
+ for ,attrib = (cl-first ,SGR-list)
+ while ,SGR-list do
+ (cond
+ ,@(cl-loop
+ for skip = 1
+ for (tag (c . rest) . rule-body) in body
+ when (not (eq tag :match)) do
+ (error "Rule (%s (%s..)..) does not start with :match" tag c)
+ when rest do
+ (setq skip (plist-get rest :skip))
+ (when (or (null skip) (cddr rest))
+ (error "Rule (%s (%s..)..) has malformed arguments: %s" tag c rest))
+ ;; Condition part of COND
+ collect `(,(if (atom c) `(eq ,c ,attrib) c)
+ ;; Body of COND
+ ,@rule-body
+ (setq ,SGR-list
+ ,(if (> skip 1)
+ `(nthcdr ,skip ,SGR-list)
+ `(cdr ,SGR-list)))))
+ (t (xterm-color--message "Not implemented SGR attribute %s" ,attrib)
+ (setq ,SGR-list (cdr ,SGR-list))))))))
+
+(defsubst xterm-color--dispatch-SGR (SGR-list)
+ "Update state machine based on SGR-LIST (list of SGR attributes /integers)."
+ (xterm-color--create-SGR-table (elem SGR-list)
+ (:match (0) (reset!)) ; RESET everything
+ (:match ((<= 30 elem 37)) (set-f! (- elem 30))) ; ANSI FG color
+ (:match ((<= 40 elem 47)) (set-b! (- elem 40))) ; ANSI BG color
+ (:match (39) (set-f! nil)) ; RESET FG color (switch to default)
+ (:match (49) (set-b! nil)) ; RESET BG color (switch to default)
+ (:match (1) (set-a! +bright+))
+ (:match (2) (unset-a! +bright+))
+ (:match (22) (unset-a! +bright+))
+
+ (:match ((and (eq 38 (cl-first SGR-list))
+ (eq 2 (cl-second SGR-list))) ; Truecolor (24-bit) FG color
+ :skip 5)
+ (when xterm-color--support-truecolor
+ (if-let ((r (cl-third SGR-list))
+ (g (cl-fourth SGR-list))
+ (b (cl-fifth SGR-list)))
+ (if (or (> r 255) (> g 255) (> b 255))
+ (xterm-color--message "SGR 38;2;%s;%s;%s exceeds range"
+ r g b)
+ (set-truecolor! r g b xterm-color--current-fg))
+ (xterm-color--message "SGR 38;2;%s;%s;%s error, expected 38;2;R;G;B"
+ r g b))))
+ (:match ((and (eq 38 (cl-first SGR-list))
+ (eq 5 (cl-second SGR-list)))
+ :skip 3) ; XTERM 256 FG color
+ (if-let ((color (cl-third SGR-list)))
+ (if (> color 255)
+ (xterm-color--message "SGR 38;5;%s exceeds range" color)
+ (set-f! color))
+ (xterm-color--message "SGR 38;5;%s error, expected 38;5;COLOR"
+ color)))
+
+ (:match ((and (eq 48 (cl-first SGR-list))
+ (eq 2 (cl-second SGR-list))) ; Truecolor (24-bit) BG color
+ :skip 5)
+ (when xterm-color--support-truecolor
+ (if-let ((r (cl-third SGR-list))
+ (g (cl-fourth SGR-list))
+ (b (cl-fifth SGR-list)))
+ (if (or (> r 255) (> g 255) (> b 255))
+ (xterm-color--message "SGR 48;2;%s;%s;%s exceeds range"
+ r g b)
+ (set-truecolor! r g b xterm-color--current-bg))
+ (xterm-color--message "SGR 48;2;%s;%s;%s error, expected 48;2;R;G;B"
+ r g b))))
+
+ (:match ((and (eq 48 (cl-first SGR-list))
+ (eq 5 (cl-second SGR-list)))
+ :skip 3) ; XTERM 256 BG color
+ (if-let ((color (cl-third SGR-list)))
+ (if (> color 255)
+ (xterm-color--message "SGR 48;5;%s exceeds range" color)
+ (set-b! color))
+ (xterm-color--message "SGR 48;5;%s error, expected 48;5;COLOR"
+ color)))
+ (:match ((<= 90 elem 97)) ; AIXTERM hi-intensity FG
+ ;; Rather than setting bright, which would be wrong,
+ ;; rescale color to fall within 8-15 so that it gets
+ ;; mapped to xterm-color-names-bright by xterm-color-256
+ (set-f! (- elem 82)))
+ ;; Same for BG, rescale to 8-15
+ (:match ((<= 100 elem 107)) (set-b! (- elem 92))) ; AIXTERM hi-intensity BG
+
+ (:match (51) (set-a! +frame+))
+ (:match (53) (set-a! +overline+))
+ (:match (54) (unset-a! +frame+))
+ (:match (55) (unset-a! +overline+))
+ (:match (4) (set-a! +underline+))
+ (:match (24) (unset-a! +underline+))
+ (:match (3) (set-a! +italic+))
+ (:match (23) (unset-a! +italic+))
+ (:match (9) (set-a! +strike-through+))
+ (:match (29) (unset-a! +strike-through+))
+ (:match (7) (set-a! +negative+))
+ (:match (27) (unset-a! +negative+))))
+
+(defsubst xterm-color--SGR-attributes (list)
+ "Convert LIFO list of SGR characters to FIFO list of SGR attributes (integers).
+
+Returns FIFO list of SGR attributes or nil on errors.
+
+Characters must be in the ASCII set 0-9 (decimal 48 to 57) and are converted
+to integer digits by subtracting 48 from each character. E.g. Character 48
+is converted to integer digit 0, character 49 to integer digit1..
+Character 59 (;) is not converted but signifies that all accumulated integer
+digits should be reversed and combined into a single integer (SGR attribute).
+
+Examples:
+
+Given (48) return (0)
+Given (59) return (0 0)
+Given (48 49 50) return (210)
+Given (48 49 50 59 50 50 59 48 49) return (10 22 210)"
+ (cl-loop
+ with mul = 1 and n = 0 and ret
+ for c in list do
+ (if (/= 59 c)
+ (let ((e (- c 48)))
+ (unless (<= 0 e 9)
+ (xterm-color--message "Invalid SGR attribute %s" c)
+ (cl-return))
+ (cl-incf n (* mul e))
+ (setq mul (* mul 10)))
+ (push n ret)
+ (setq n 0 mul 1))
+ finally return (push n ret)))
+
+
+;;;
+;;; CSI state machine
+;;;
+
+
+(defsubst xterm-color--dispatch-CSI ()
+ "Update state machine based on CSI parameters collected so far.
+Parameters are taken from `xterm-color--CSI-list' which stores them
+in LIFO order."
+ (let* ((csi xterm-color--CSI-list)
+ (term (car csi)) ; final parameter, terminator
+ (params (cdr csi))) ; rest of parameters, LIFO order
+ (setq xterm-color--CSI-list nil)
+ (cond ((eq ?m term)
+ ;; SGR
+ (let ((SGR-list (if (null params) '(0)
+ (xterm-color--SGR-attributes params))))
+ (when SGR-list
+ (xterm-color--dispatch-SGR SGR-list))))
+ (t
+ (xterm-color--message "%s CSI not implemented" csi)))))
+
+(defmacro xterm-color--with-ANSI-macro-helpers (&rest body)
+ (declare (indent defun))
+ `(xterm-color--with-SGR-constants
+ (cl-symbol-macrolet ((fg xterm-color--current-fg)
+ (bg xterm-color--current-bg)
+ (attrs xterm-color--attributes)
+ (bold-bright xterm-color-use-bold-for-bright))
+ (cl-macrolet
+ ((out! (x) `(push ,x result))
+ (push-char! (c) `(push ,c xterm-color--char-list))
+ (push-csi! (c) `(push ,c xterm-color--CSI-list))
+ (state! (s) `(setq state ,s))
+ (graphics? () `(or fg bg (/= attrs 0)))
+ (has? (attr) `(/= (logand ,attr attrs) 0))
+ (fmt-24bit (color) `(format "#%06x" ,color))
+ (fmt-256 (color) `(xterm-color-256 ,color))
+
+ ;; Unpacks a packed truecolor value (as stored in
+ ;; `xterm-color--current-fg' and `xterm-color--current-fg'.
+ (unpack (color) `(ash ,color -9))
+
+ ;; To avoid hash collisions, a different packing scheme is used
+ ;; for hash table keys. It can encode two colors (foreground
+ ;; and background) that can either be truecolor 24bit or XTerm 256
+ ;; color 8bit. XTerm 256 color values subsume ANSI colors, a
+ ;; separate encoding scheme is not needed.
+ ;;
+ ;; The scheme used also accounts for the combination of a truecolor
+ ;; with an XTerm 256 color as part of the same hashed entry. Since
+ ;; two different hash tables are used to work around 32bit Emacs
+ ;; limited integer range, two packing schemes are needed:
+ ;;
+ ;; High< 25 bits >Low
+ ;; ATTR[7 bits]BG[9 bits]FG[9 bits] where BG and FG are each
+ ;; encoded as the 8bit color value shifted left by 1 and combined
+ ;; with a flag bit which is set when the color is present.
+ ;;
+ ;; High< 59 bits >Low
+ ;; ATTR[7 bits]BG[26 bits]FG[26 bits] where BG and FG are each
+ ;; encoded as the 24bit (RGB) or 8bit color value shifted left by
+ ;; 2 and combined with 2 flag bits that are set when the value
+ ;; is 24bit (high bit) and when the color is present (low bit).
+ (pack-256 (color) `(if ,color (logior (ash ,color 1) 1) 0))
+ (pack-24bit (color) `(if ,color
+ (if (> ,color 255)
+ (logior (ash (unpack ,color) 2) 3)
+ (logior (ash ,color 2) 1))
+ 0))
+ ;; If at least one of foreground / background color is a 24bit
+ ;; truecolor value: Second packing scheme with
+ ;; `xterm-color--truecolor-face-cache' is used.
+ ;;
+ ;; Every other case, including when no colors are present:
+ ;; First packing scheme with `xterm-color--face-cache' is used.
+ (pack-key-into (k) `(cond ((or (and fg (> fg 255))
+ (and bg (> bg 255)))
+ ;; At least one truecolor 24bit value
+ (setq ,k (logior (ash attrs 52)
+ (ash (pack-24bit bg) 26)
+ (pack-24bit fg)))
+ xterm-color--truecolor-face-cache)
+ (t ;; No truecolor 24bit value
+ (setq ,k (logior (ash attrs 18)
+ (ash (pack-256 bg) 9)
+ (pack-256 fg)))
+ xterm-color--face-cache)))
+
+ (face! (k v) `(setq plistf (plist-put plistf ,k ,v)))
+ (make-color-fg () `(if (and bold-bright
+ (< fg 256)
+ (or (has? +bright+) (<= 8 fg 15)))
+ (progn (face! :weight 'bold)
+ (face! :foreground
+ (fmt-256 (if (<= 8 fg) (- fg 8) fg))))
+ (face! :foreground
+ (if (> fg 255)
+ (fmt-24bit (unpack fg))
+ (fmt-256 (if (and (<= fg 7) (has? +bright+))
+ (+ fg 8)
+ fg))))))
+ (make-color-bg () `(face! :background (cond ((> bg 255) (fmt-24bit (unpack bg)))
+ (t (fmt-256 bg)))))
+ (make-face () `(let* (k
+ (table (pack-key-into k)))
+ (or (gethash k table)
+ (let (plistf)
+ (when (has? +italic+) (face! :slant 'italic))
+ (when (has? +underline+) (face! :underline t))
+ (when (has? +strike-through+) (face! :strike-through t))
+ (when (has? +negative+) (face! :inverse-video t))
+ (when (has? +overline+) (face! :overline t))
+ (when (has? +frame+) (face! :box t))
+
+ (cond (fg (make-color-fg))
+ (t (when (and bold-bright (has? +bright+))
+ (face! :weight 'bold))))
+
+ (when bg (make-color-bg))
+ (puthash k plistf table)))))
+ (maybe-fontify () '(when xterm-color--char-list
+ (let ((s (concat (nreverse xterm-color--char-list))))
+ (when (and xterm-color-render (graphics?))
+ (add-text-properties
+ 0 (length s)
+ (list 'xterm-color t
+ (if font-lock-mode 'font-lock-face 'face)
+ (make-face))
+ s))
+ (out! s))
+ (setq xterm-color--char-list nil))))
+ ,@body))))
+
+
+;;;
+;;; Exports
+;;;
+
+
+;;;###autoload
+(defun xterm-color-filter-strip (string)
+ "Translate ANSI color sequences in STRING into text properties.
+Return new STRING with text properties applied.
+
+In order to get maximum performance, this function strips text properties
+if they are present in STRING."
+ (unless xterm-color--face-cache
+ (setq xterm-color--face-cache
+ (make-hash-table :weakness 'value)))
+ (unless xterm-color--truecolor-face-cache
+ (setq xterm-color--truecolor-face-cache
+ (make-hash-table :weakness 'value)))
+ (xterm-color--with-ANSI-macro-helpers
+ (cl-loop
+ with state = xterm-color--state and result
+ for char across string do
+ (cond
+ ((eq state :char)
+ (cond
+ ((eq char 27) ; ESC
+ (maybe-fontify)
+ (state! :ansi-esc))
+ (t
+ (if (graphics?)
+ (push-char! char)
+ (out! (list char))))))
+ ((eq state :ansi-esc)
+ (cond ((eq char ?\[)
+ (state! :ansi-csi))
+ ((eq char ?\])
+ (state! :ansi-osc))
+ ((or (eq char ?\()
+ (eq char ?\)))
+ (state! :set-char))
+ (t
+ (push-char! char)
+ (state! :char))))
+ ((eq state :ansi-csi)
+ (push-csi! char)
+ (when (and (>= char #x40)
+ (<= char #x7e))
+ (xterm-color--dispatch-CSI)
+ (state! :char)))
+ ((eq state :ansi-osc)
+ ;; OSC sequences are skipped
+ (cond ((eq char 7)
+ (state! :char))
+ ((eq char 27)
+ ;; ESC
+ (state! :ansi-osc-esc))))
+ ((eq state :ansi-osc-esc)
+ (cond ((eq char ?\\)
+ (state! :char))
+ (t (state! :ansi-osc))))
+ ((eq state :set-char)
+ (xterm-color--message "%s SET-CHAR not implemented" char)
+ (state! :char)))
+ finally return
+ (progn (when (eq state :char) (maybe-fontify))
+ (setq xterm-color--state state)
+ (apply 'concat (nreverse result))))))
+
+;;;###autoload
+(defun xterm-color-filter (string)
+ "Translate ANSI color sequences in STRING into text properties.
+Return new STRING with text properties applied.
+
+This function checks if `xterm-color-preserve-properties' is non-nil
+and only calls `xterm-color-filter-strip' on substrings that do not
+have text properties applied (passing through the rest unmodified).
+Preserving properties in this fashion is not very robust as there may
+be situations where text properties are applied on ANSI data, which
+will desync the state machine.
+
+Preserving properties works ok with and is really meant for eshell.
+
+This can be inserted into `comint-preoutput-filter-functions'."
+ (if (not xterm-color-preserve-properties)
+ (xterm-color-filter-strip string)
+ (cl-loop
+ with result
+ for (_ props substring) in (xterm-color--string-properties string) do
+ (push (if props substring (xterm-color-filter-strip substring))
+ result)
+ finally return (apply 'concat (nreverse result)))))
+
+;;;###autoload
+(defun xterm-color-256 (color)
+ (cond ((and (>= color 232)
+ (<= color 255))
+ ;; Grayscale
+ (let ((val (+ 8 (* (- color 232) 10))))
+ (format "#%02x%02x%02x" val val val)))
+ ((<= color 7)
+ ;; Normal ANSI color
+ (aref xterm-color-names color))
+ ((and (>= color 8)
+ (<= color 15))
+ ;; Bright ANSI color
+ (aref xterm-color-names-bright (- color 8)))
+ (t (let* ((color (- color 16))
+ (red (/ color 36))
+ (color (mod color 36))
+ (green (/ color 6))
+ (color (mod color 6))
+ (blue color))
+ ;; XTERM 256 color
+ (format "#%02x%02x%02x"
+ (aref +xterm-color--table-256+ red)
+ (aref +xterm-color--table-256+ green)
+ (aref +xterm-color--table-256+ blue))))))
+
+
+;;;
+;;; Interactive
+;;;
+
+
+;;;###autoload
+(cl-defun xterm-color-colorize-buffer (&optional use-overlays)
+ "Apply `xterm-color-filter' to current buffer, and replace its contents.
+Colors are applied using 'face, unless font-lock-mode is active, in
+which case 'font-lock-face is used. Operation with font-lock mode active
+is not recommended.
+
+If USE-OVERLAYS is non-nil, colors are applied to the buffer using overlays
+instead of text properties. A C-u prefix arg causes overlays to be used."
+ (interactive "P")
+ (let ((read-only-p buffer-read-only))
+ (when read-only-p
+ (unless (y-or-n-p "Buffer is read only, continue colorizing? ")
+ (cl-return-from xterm-color-colorize-buffer))
+ (read-only-mode -1))
+ (insert (xterm-color-filter (delete-and-extract-region (point-min) (point-max))))
+ (when (and xterm-color-render use-overlays)
+ (xterm-color--convert-text-properties-to-overlays (point-min) (point-max)))
+ (goto-char (point-min))
+ (when read-only-p (read-only-mode 1))))
+
+;;;###autoload
+(defun xterm-color-clear-cache ()
+ "Clear xterm color face attribute cache.
+You may want to call this if you change `xterm-color-names' or
+`xterm-color-names-bright' at runtime and you want to see the changes
+take place in a pre-existing buffer that has had xterm-color initialized.
+
+Since the cache is buffer-local and created on-demand when needed, this has no
+effect when called from a buffer that does not have a cache."
+ (interactive)
+ (and xterm-color--face-cache
+ (clrhash xterm-color--face-cache)
+ (xterm-color--message "Cleared face attribute cache"))
+ (and xterm-color--truecolor-face-cache
+ (clrhash xterm-color--truecolor-face-cache)
+ (xterm-color--message "Cleared truecolor face attribute cache")))
+
+
+;;;
+;;; Tests
+;;;
+
+
+(defmacro xterm-color--bench (path &optional repetitions)
+ `(benchmark-run-compiled ,repetitions
+ (with-temp-buffer
+ (insert-file-contents-literally ,path)
+ (xterm-color-colorize-buffer))))
+
+(defvar xterm-color--test-do-filter t)
+
+(cl-defmacro xterm-color--with-tests (&body body)
+ `(cl-labels ((ansi-filter (msg &rest args)
+ (insert
+ (if xterm-color--test-do-filter
+ (xterm-color-filter
+ (apply #'format msg args))
+ (apply #'format msg args))))
+ (test (name &rest attribs)
+ (ansi-filter "\x1b[0;%smThis is only a test!\x1b[0m\t --[ %s\n"
+ (mapconcat #'identity attribs ";")
+ name)))
+ ,@body))
+
+(defun xterm-color--test-ansi ()
+ (xterm-color--with-tests
+ (let ((test-attributes
+ '(("1" . "bright")
+ ("51" . "frame")
+ ("3" . "italic")
+ ("4" . "underline")
+ ("7" . "negative")
+ ("9" . "strike through")
+ ("53" . "overline")
+ ("1;51" . "bright + frame")
+ ("1;3" . "bright + italic")
+ ("1;4" . "bright + underline")
+ ("1;7" . "bright + negative")
+ ("1;9" . "bright + strike through")
+ ("1;53" . "bright + overline"))))
+
+ ;; Attributes (no color)
+ (insert "* ANSI attributes (default colors)\n")
+
+ (if xterm-color-use-bold-for-bright
+ (insert " Expect: Bold instead of bright")
+ (insert " Expect: Bright not to be rendered since no foreground color is set"))
+ (insert "\n\n")
+
+ (cl-loop for (attrib . name) in test-attributes
+ do (test name attrib)
+ finally (insert "\n"))
+
+ (insert "* ANSI attributes (blue foreground)\n")
+
+ (if xterm-color-use-bold-for-bright
+ (insert " Expect: Bold instead of bright")
+ (insert " Expect: Bright rendered as bright color"))
+ (insert "\n\n")
+
+ (cl-loop for (attrib . name) in test-attributes
+ do (test name "34" attrib)
+ finally (insert "\n"))
+
+ (insert "* ANSI attributes (blue background)\n")
+
+ (if xterm-color-use-bold-for-bright
+ (insert " Expect: Bold instead of bright")
+ (insert " Expect: Bright not to be rendered since no foreground color is set"))
+ (insert "\n\n")
+
+ (cl-loop for (attrib . name) in test-attributes
+ do (test name "44" attrib)
+ finally (insert "\n"))
+
+ (insert "* ANSI attributes (AIXTERM blue foreground)\n")
+
+ (if xterm-color-use-bold-for-bright
+ (insert " Expect: Bold instead of bright")
+ (insert " Expect: Bright color everywhere due to AIXTERM"))
+ (insert "\n\n")
+
+ (cl-loop for (attrib . name) in test-attributes
+ do (test name "94" attrib)
+ finally (insert "\n"))
+
+ (insert "* ANSI attributes (AIXTERM red background)\n")
+ (insert " Expect: Bright background color due to AIXTERM\n")
+ (if xterm-color-use-bold-for-bright
+ (insert " Expect: Bold instead of bright for foreground\n\n")
+ (insert "\n"))
+
+ (cl-loop for (attrib . name) in test-attributes
+ do (test name "101" attrib)
+ finally (insert "\n"))
+
+ (insert "* Misc\n")
+ (if xterm-color-use-bold-for-bright
+ (progn
+ (insert " Expect: Bold instead of bright\n")
+ (insert " Otherwise bright rendered as normal intensity\n\n"))
+ (insert "\n"))
+
+ (insert "; Resetting FG color should not affect other SGR bits\n")
+ (ansi-filter "Default \x1b[34;1mBright blue\x1b[39m Reset-fg-color \x1b[34mBlue (bright)\x1b[0m\n\n")
+ (insert "; AIXTERM bright color should not set bright SGR bit\n")
+ (ansi-filter "Default \x1b[94mBright blue\x1b[34m Switch-to-blue (normal)\x1b[0m\n")
+ (insert "\n"))))
+
+(defun xterm-color--test-xterm ()
+ (xterm-color--with-tests
+ ;; System colors
+ (cl-loop for color from 40 to 47
+ do (ansi-filter "\x1b[0;%sm " color)
+ finally (ansi-filter "\x1b[0m * ANSI system colors\n"))
+
+ ;; Normal ANSI colors mapped to XTERM
+ (cl-loop for color from 0 to 7
+ do (ansi-filter "\x1b[48;5;%sm " color)
+ finally (ansi-filter "\x1b[0m * ANSI colors mapped to XTERM\n"))
+
+ ;; Bright ANSI colors mapped to XTERM
+ (cl-loop for color from 8 to 15
+ do (ansi-filter "\x1b[48;5;%sm " color)
+ finally (ansi-filter "\x1b[0m * ANSI bright colors mapped to XTERM\n\n"))
+
+ ;; XTERM 256 color cubes
+ (insert "* XTERM 256 color cubes\n\n")
+
+ (cl-loop for green from 0 to 5 do
+ (cl-loop for red from 0 to 5 do
+ (cl-loop for blue from 0 to 5
+ for color = (+ 16 (* 36 red) (* green 6) blue)
+ do (ansi-filter "\x1b[48;5;%sm \x1b[0m" color))
+ (ansi-filter "\x1b[0m "))
+ (insert "\n"))
+
+ ;; Truecolor color ramps
+ (insert "\n")
+ (insert "* Truecolor\n\n")
+ (cond (xterm-color--support-truecolor
+ ;; Adapted from: https://gist.github.com/XVilka/8346728
+ (cl-loop
+ with steps = 77
+ for c from 0 below steps
+ for r = (- 255 (* c (/ 255 steps)))
+ for g = (* c (/ 510 steps))
+ for b = (* c (/ 255 steps)) do
+ (when (> g 255) (setq g (- 510 g)))
+ (ansi-filter "\x1b[48;2;%s;%s;%sm \x1b[m" r g b)))
+ (t
+ (insert "Truecolor is not supported on Emacs 32bit")))
+
+ (insert "\n\n")
+ (insert "* XTERM color grayscale ramp\n\n")
+
+ (cl-loop for color from 232 to 255
+ do (ansi-filter "\x1b[48;5;%sm " color)
+ finally (ansi-filter "\x1b[0m\n\n"))))
+
+;;;###autoload
+(defun xterm-color-test ()
+ "Create, display and render a new buffer containing ANSI control sequences."
+ (interactive)
+ (let* ((name (generate-new-buffer-name "*xterm-color-test*"))
+ (buf (get-buffer-create name)))
+ (switch-to-buffer buf))
+
+ (xterm-color--test-xterm)
+
+ (let ((xterm-color-use-bold-for-bright nil))
+ (xterm-color--test-ansi))
+ (xterm-color-clear-cache)
+
+ (insert "; Temporarily setting `xterm-color-use-bold-for-bright' to T\n")
+ (insert "; Current font needs to have a bold variant for following tests\n\n")
+
+ (let ((xterm-color-use-bold-for-bright t))
+ (xterm-color--test-ansi))
+
+ (setq buffer-read-only t)
+ (goto-char (point-min)))
+
+;;;###autoload
+(defun xterm-color-test-raw ()
+ "Create and display a new buffer containing ANSI SGR control sequences.
+ANSI sequences are not processed. One can use a different Emacs package,
+such as ansi-color.el to do so. This is really meant to be used for easy
+comparisons/benchmarks with libraries that offer similar functionality."
+ (interactive)
+ (let* ((name (generate-new-buffer-name "*xterm-color-test-raw*"))
+ (buf (get-buffer-create name)))
+ (switch-to-buffer buf))
+
+ (let (xterm-color--test-do-filter)
+ (xterm-color--test-xterm)
+ (xterm-color--test-ansi))
+ (goto-char (point-min)))
+
+(provide 'xterm-color)
+;;; xterm-color.el ends here