Updating Doom Emacs.

This commit is contained in:
Derek Taylor
2020-06-19 22:43:40 -05:00
parent 0f664d532a
commit a5c86c514a
453 changed files with 13527 additions and 12455 deletions

View File

@@ -116,7 +116,7 @@ There is no guarantee your language mode will have completion support.
Some, like ~lua-mode~, don't have completion support in Emacs at all. Others may
requires additional setup to get code completion working. For instance,
~go-mode~ requires ~guru~ to be installed on your system, and ~enh-ruby-mode~
~go-mode~ requires ~guru~ to be installed on your system, and ~ruby-mode~
requires that you have a Robe server running (~M-x robe-start~).
Check the relevant module's documentation for this kind of information.

View File

@@ -67,11 +67,10 @@ Examples:
;;;###autoload
(defun +company-init-backends-h ()
"Set `company-backends' for the current buffer."
(if (not company-mode)
(remove-hook 'change-major-mode-after-body-hook #'+company-init-backends-h 'local)
(unless (eq major-mode 'fundamental-mode)
(setq-local company-backends (+company--backends)))
(add-hook 'change-major-mode-after-body-hook #'+company-init-backends-h nil 'local)))
(or (memq major-mode '(fundamental-mode special-mode))
buffer-read-only
(doom-temp-buffer-p (or (buffer-base-buffer) (current-buffer)))
(setq-local company-backends (+company--backends))))
(put '+company-init-backends-h 'permanent-local-hook t)

View File

@@ -2,25 +2,49 @@
(use-package! company
:commands company-complete-common company-manual-begin company-grab-line
:after-call pre-command-hook after-find-file
:hook (doom-first-input . global-company-mode)
:init
(setq company-minimum-prefix-length 2
(setq company-idle-delay 0.25
company-minimum-prefix-length 2
company-tooltip-limit 14
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil
company-dabbrev-code-other-buffers t
company-tooltip-align-annotations t
company-require-match 'never
company-global-modes
'(not erc-mode message-mode help-mode gud-mode eshell-mode)
company-backends '(company-capf)
company-frontends
'(company-pseudo-tooltip-frontend
company-echo-metadata-frontend))
'(not erc-mode message-mode help-mode gud-mode)
company-frontends '(company-pseudo-tooltip-frontend
company-echo-metadata-frontend)
;; Buffer-local backends will be computed when loading a major mode, so
;; only specify a global default here.
company-backends '(company-capf)
;; Company overrides `company-active-map' based on
;; `company-auto-complete-chars'; no magic please!
company-auto-complete-chars nil
;; Only search the current buffer for `company-dabbrev' (a backend that
;; suggests text your open buffers). This prevents Company from causing
;; lag once you have a lot of buffers open.
company-dabbrev-other-buffers nil
;; Make `company-dabbrev' fully case-sensitive, to improve UX with
;; domain-specific words with particular casing.
company-dabbrev-ignore-case nil
company-dabbrev-downcase nil)
:config
(when (featurep! :editor evil)
(add-hook 'company-mode-hook #'evil-normalize-keymaps)
(unless (featurep! +childframe)
;; Don't persist company popups when switching back to normal mode.
;; `company-box' aborts on mode switch so it doesn't need this.
(add-hook! 'evil-normal-state-entry-hook
(defun +company-abort-h ()
;; HACK `company-abort' doesn't no-op if company isn't active; causing
;; unwanted side-effects, like the suppression of messages in the
;; echo-area.
;; REVIEW Revisit this to refactor; shouldn't be necessary!
(when company-candidates
(company-abort)))))
;; Allow users to switch between backends on the fly. E.g. C-x C-s followed
;; by C-x C-n, will switch from `company-yasnippet' to
;; `company-dabbrev-code'.
@@ -28,8 +52,7 @@
:before #'company-begin-backend
(company-abort)))
(add-hook 'company-mode-hook #'+company-init-backends-h)
(global-company-mode +1))
(add-hook 'after-change-major-mode-hook #'+company-init-backends-h 'append))
(use-package! company-tng
@@ -49,8 +72,7 @@
;; Packages
(after! company-files
(pushnew! company-files--regexps
"file:\\(\\(?:\\.\\{1,2\\}/\\|~/\\|/\\)[^\]\n]*\\)"))
(add-to-list 'company-files--regexps "file:\\(\\(?:\\.\\{1,2\\}/\\|~/\\|/\\)[^\]\n]*\\)"))
(use-package! company-prescient
@@ -70,47 +92,44 @@
company-box-max-candidates 50
company-box-icons-alist 'company-box-icons-all-the-icons
company-box-icons-functions
'(+company-box-icons--yasnippet-fn
company-box-icons--lsp
+company-box-icons--elisp-fn
company-box-icons--acphp)
(cons #'+company-box-icons--elisp-fn
(delq 'company-box-icons--elisp
company-box-icons-functions))
company-box-icons-all-the-icons
`((Unknown . ,(all-the-icons-material "find_in_page" :height 0.8 :face 'all-the-icons-purple))
(Text . ,(all-the-icons-material "text_fields" :height 0.8 :face 'all-the-icons-green))
(Method . ,(all-the-icons-material "functions" :height 0.8 :face 'all-the-icons-red))
(Function . ,(all-the-icons-material "functions" :height 0.8 :face 'all-the-icons-red))
(Constructor . ,(all-the-icons-material "functions" :height 0.8 :face 'all-the-icons-red))
(Field . ,(all-the-icons-material "functions" :height 0.8 :face 'all-the-icons-red))
(Variable . ,(all-the-icons-material "adjust" :height 0.8 :face 'all-the-icons-blue))
(Class . ,(all-the-icons-material "class" :height 0.8 :face 'all-the-icons-red))
(Interface . ,(all-the-icons-material "settings_input_component" :height 0.8 :face 'all-the-icons-red))
(Module . ,(all-the-icons-material "view_module" :height 0.8 :face 'all-the-icons-red))
(Property . ,(all-the-icons-material "settings" :height 0.8 :face 'all-the-icons-red))
(Unit . ,(all-the-icons-material "straighten" :height 0.8 :face 'all-the-icons-red))
(Value . ,(all-the-icons-material "filter_1" :height 0.8 :face 'all-the-icons-red))
(Enum . ,(all-the-icons-material "plus_one" :height 0.8 :face 'all-the-icons-red))
(Keyword . ,(all-the-icons-material "filter_center_focus" :height 0.8 :face 'all-the-icons-red))
(Snippet . ,(all-the-icons-material "short_text" :height 0.8 :face 'all-the-icons-red))
(Color . ,(all-the-icons-material "color_lens" :height 0.8 :face 'all-the-icons-red))
(File . ,(all-the-icons-material "insert_drive_file" :height 0.8 :face 'all-the-icons-red))
(Reference . ,(all-the-icons-material "collections_bookmark" :height 0.8 :face 'all-the-icons-red))
(Folder . ,(all-the-icons-material "folder" :height 0.8 :face 'all-the-icons-red))
(EnumMember . ,(all-the-icons-material "people" :height 0.8 :face 'all-the-icons-red))
(Constant . ,(all-the-icons-material "pause_circle_filled" :height 0.8 :face 'all-the-icons-red))
(Struct . ,(all-the-icons-material "streetview" :height 0.8 :face 'all-the-icons-red))
(Event . ,(all-the-icons-material "event" :height 0.8 :face 'all-the-icons-red))
(Operator . ,(all-the-icons-material "control_point" :height 0.8 :face 'all-the-icons-red))
(TypeParameter . ,(all-the-icons-material "class" :height 0.8 :face 'all-the-icons-red))
;; (Template . ,(company-box-icons-image "Template.png"))))
(Yasnippet . ,(all-the-icons-material "short_text" :height 0.8 :face 'all-the-icons-green))
(ElispFunction . ,(all-the-icons-material "functions" :height 0.8 :face 'all-the-icons-red))
(ElispVariable . ,(all-the-icons-material "check_circle" :height 0.8 :face 'all-the-icons-blue))
(ElispFeature . ,(all-the-icons-material "stars" :height 0.8 :face 'all-the-icons-orange))
(ElispFace . ,(all-the-icons-material "format_paint" :height 0.8 :face 'all-the-icons-pink))))
(let ((all-the-icons-scale-factor 0.8))
`((Unknown . ,(all-the-icons-material "find_in_page" :face 'all-the-icons-purple))
(Text . ,(all-the-icons-material "text_fields" :face 'all-the-icons-green))
(Method . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
(Function . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
(Constructor . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
(Field . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
(Variable . ,(all-the-icons-material "adjust" :face 'all-the-icons-blue))
(Class . ,(all-the-icons-material "class" :face 'all-the-icons-red))
(Interface . ,(all-the-icons-material "settings_input_component" :face 'all-the-icons-red))
(Module . ,(all-the-icons-material "view_module" :face 'all-the-icons-red))
(Property . ,(all-the-icons-material "settings" :face 'all-the-icons-red))
(Unit . ,(all-the-icons-material "straighten" :face 'all-the-icons-red))
(Value . ,(all-the-icons-material "filter_1" :face 'all-the-icons-red))
(Enum . ,(all-the-icons-material "plus_one" :face 'all-the-icons-red))
(Keyword . ,(all-the-icons-material "filter_center_focus" :face 'all-the-icons-red))
(Snippet . ,(all-the-icons-material "short_text" :face 'all-the-icons-red))
(Color . ,(all-the-icons-material "color_lens" :face 'all-the-icons-red))
(File . ,(all-the-icons-material "insert_drive_file" :face 'all-the-icons-red))
(Reference . ,(all-the-icons-material "collections_bookmark" :face 'all-the-icons-red))
(Folder . ,(all-the-icons-material "folder" :face 'all-the-icons-red))
(EnumMember . ,(all-the-icons-material "people" :face 'all-the-icons-red))
(Constant . ,(all-the-icons-material "pause_circle_filled" :face 'all-the-icons-red))
(Struct . ,(all-the-icons-material "streetview" :face 'all-the-icons-red))
(Event . ,(all-the-icons-material "event" :face 'all-the-icons-red))
(Operator . ,(all-the-icons-material "control_point" :face 'all-the-icons-red))
(TypeParameter . ,(all-the-icons-material "class" :face 'all-the-icons-red))
(Template . ,(all-the-icons-material "short_text" :face 'all-the-icons-green))
(ElispFunction . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
(ElispVariable . ,(all-the-icons-material "check_circle" :face 'all-the-icons-blue))
(ElispFeature . ,(all-the-icons-material "stars" :face 'all-the-icons-orange))
(ElispFace . ,(all-the-icons-material "format_paint" :face 'all-the-icons-pink)))))
(defun +company-box-icons--yasnippet-fn (candidate)
(when (get-text-property 0 'yas-annotation candidate)
'Yasnippet))
(delq! 'company-echo-metadata-frontend company-frontends)
(defun +company-box-icons--elisp-fn (candidate)
(when (derived-mode-p 'emacs-lisp-mode)
@@ -118,7 +137,14 @@
(cond ((fboundp sym) 'ElispFunction)
((boundp sym) 'ElispVariable)
((featurep sym) 'ElispFeature)
((facep sym) 'ElispFace))))))
((facep sym) 'ElispFace)))))
(defadvice! +company-remove-scrollbar-a (orig-fn &rest args)
"This disables the company-box scrollbar, because:
https://github.com/sebastiencs/company-box/issues/44"
:around #'company-box--update-scrollbar
(letf! ((#'display-buffer-in-side-window #'ignore))
(apply orig-fn args))))
(use-package! company-dict

View File

@@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*-
;;; completion/company/packages.el
(package! company)
(package! company-dict)
(package! company-prescient)
(package! company :pin "6333fc4ebbbf4d28e834de8715561e984f149ecb")
(package! company-dict :pin "cd7b8394f6014c57897f65d335d6b2bd65dab1f4")
(package! company-prescient :pin "0f4a89bdec61395138d968a38d375e63ccfbed63")
(when (featurep! +childframe)
(package! company-box))
(package! company-box :pin "3814fcb14e92f4b85b19e664e216a7c8d5c7144d"))

View File

@@ -38,7 +38,7 @@ workspace."
;;; Project search
;;;###autoload
(cl-defun +helm-file-search (&key query in all-files (recursive t))
(cl-defun +helm-file-search (&key query in all-files (recursive t) _prompt args)
"Conduct a file search using ripgrep.
:query STRING
@@ -52,10 +52,13 @@ workspace."
(unless (executable-find "rg")
(user-error "Couldn't find ripgrep in your PATH"))
(require 'helm-rg)
(let ((helm-rg-default-directory (or in (doom-project-root) default-directory))
(let ((this-command 'helm-rg)
(helm-rg-default-directory (or in (doom-project-root) default-directory))
(helm-rg-default-extra-args
(delq nil (list (when all-files "-z -uu")
(unless recursive "--maxdepth 1")))))
(delq nil (append (list (when all-files "-z -uu")
(unless recursive "--maxdepth 1"))
args))))
(setq deactivate-mark t)
(helm-rg (or query
(when (use-region-p)
(let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))

View File

@@ -23,6 +23,7 @@ bottom, which is easier on the eyes on big displays."
(setq +helm--posframe-buffer buffer)
:position (point)
:poshandler +helm-posframe-handler
:respect-header-line helm-echo-input-in-header-line
:width
(max (cl-typecase .width
(integer .width)

View File

@@ -23,8 +23,7 @@ be negative.")
;;; Packages
(use-package! helm-mode
:defer t
:after-call pre-command-hook
:hook (doom-first-input . helm-mode)
:init
(map! [remap apropos] #'helm-apropos
[remap find-library] #'helm-locate-library
@@ -43,7 +42,6 @@ be negative.")
[remap recentf-open-files] #'helm-recentf
[remap yank-pop] #'helm-show-kill-ring)
:config
(helm-mode +1)
;; helm is too heavy for `find-file-at-point'
(add-to-list 'helm-completing-read-handlers-alist (cons #'find-file-at-point nil)))
@@ -57,8 +55,6 @@ be negative.")
helm-mode-line-string nil
helm-ff-auto-update-initial-value nil
helm-find-files-doc-header nil
;; Don't override evil-ex's completion
helm-mode-handle-completion-in-region nil
;; Default helm window sizes
helm-display-buffer-default-width nil
helm-display-buffer-default-height 0.25
@@ -73,38 +69,37 @@ be negative.")
:init
(when (featurep! +childframe)
;; If this is set to 'iconify-top-level then Emacs will be minimized upon
;; helm completion.
(setq iconify-child-frame 'make-invisible)
(setq helm-display-function #'+helm-posframe-display-fn))
(let ((fuzzy (featurep! +fuzzy)))
(setq helm-M-x-fuzzy-match fuzzy
helm-apropos-fuzzy-match fuzzy
helm-apropos-fuzzy-match fuzzy
(setq helm-apropos-fuzzy-match fuzzy
helm-bookmark-show-location fuzzy
helm-buffers-fuzzy-matching fuzzy
helm-completion-in-region-fuzzy-match fuzzy
helm-completion-in-region-fuzzy-match fuzzy
helm-ff-fuzzy-matching fuzzy
helm-file-cache-fuzzy-match fuzzy
helm-flx-for-helm-locate fuzzy
helm-imenu-fuzzy-match fuzzy
helm-lisp-fuzzy-completion fuzzy
helm-locate-fuzzy-match fuzzy
helm-mode-fuzzy-match fuzzy
helm-projectile-fuzzy-match fuzzy
helm-recentf-fuzzy-match fuzzy
helm-semantic-fuzzy-match fuzzy))
helm-semantic-fuzzy-match fuzzy)
;; Make sure that we have helm-multi-matching or fuzzy matching,
;; (as prescribed by the fuzzy flag) also in the following cases:
;; - helmized commands that use `completion-at-point' and similar functions
;; - native commands that fall back to `completion-styles' like `helm-M-x'
(push (if EMACS27+
(if fuzzy 'flex 'helm)
(if fuzzy 'helm-flex 'helm))
completion-styles))
:config
(set-popup-rule! "^\\*helm" :vslot -100 :size 0.22 :ttl nil)
;; HACK Doom doesn't support these commands, which invite the user to install
;; the package via ELPA. Force them to use +helm/* instead, because they work
;; out of the box.
(advice-add #'helm-projectile-rg :override #'+helm/project-search)
(advice-add #'helm-projectile-ag :override #'+helm/project-search)
(advice-add #'helm-projectile-grep :override #'+helm/project-search)
;; Hide the modeline
;; Hide the modeline in helm windows as it serves little purpose.
(defun +helm--hide-mode-line (&rest _)
(with-current-buffer (helm-buffer-get)
(unless helm-mode-line-string
@@ -113,11 +108,13 @@ be negative.")
(advice-add #'helm-display-mode-line :override #'+helm--hide-mode-line)
(advice-add #'helm-ag-show-status-default-mode-line :override #'ignore)
;; Hide minibuffer if `helm-echo-input-in-header-line'
(add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
;; Use helpful instead of describe-* to display documentation
(dolist (fn '(helm-describe-variable helm-describe-function))
(advice-add fn :around #'doom-use-helpful-a)))
(use-package! helm-flx
:when (featurep! +fuzzy)
:hook (helm-mode . helm-flx-mode)
@@ -131,7 +128,7 @@ be negative.")
"C-c C-e" #'helm-rg--bounce)
(map! :map helm-rg--bounce-mode-map
"q" #'kill-current-buffer
"C-c C-c" (λ! (helm-rg--bounce-dump) (kill-current-buffer))
"C-c C-c" (cmd! (helm-rg--bounce-dump) (kill-current-buffer))
"C-x C-c" #'helm-rg--bounce-dump-current-file
"C-c C-k" #'kill-current-buffer))
@@ -183,3 +180,7 @@ be negative.")
(lambda (buf &optional _resume) (pop-to-buffer buf)))
(global-set-key [remap swiper] #'swiper-helm)
(add-to-list 'swiper-font-lock-exclude #'+doom-dashboard-mode nil #'eq))
(use-package! helm-descbinds
:hook (helm-mode . helm-descbinds-mode))

View File

@@ -1,16 +1,19 @@
;; -*- no-byte-compile: t; -*-
;;; completion/helm/packages.el
(package! helm)
(package! helm-rg)
(package! helm-c-yasnippet)
(package! helm-company)
(package! helm-describe-modes :recipe (:host github :repo "emacs-helm/helm-describe-modes"))
(package! helm-projectile)
(package! swiper-helm)
(package! helm :pin "b6db9fb47a8900704394e63b795f4a54cb4701a8")
(package! helm-rg :pin "785a80fe5cc87e27c5ea3d00a70049028d9e2847")
(package! helm-c-yasnippet :pin "65ca732b510bfc31636708aebcfe4d2d845b59b0")
(package! helm-company :pin "6eb5c2d730a60e394e005b47c1db018697094dde")
(package! helm-describe-modes
:recipe (:host github :repo "emacs-helm/helm-describe-modes")
:pin "11fb36af119b784539d31c6160002de1957408aa")
(package! helm-projectile :pin "5328b74dddcee8d1913803ca8167868831a07463")
(package! swiper-helm :pin "93fb6db87bc6a5967898b5fd3286954cc72a0008")
(when (featurep! +fuzzy)
(package! helm-flx))
(package! helm-flx :pin "6640fac5cb16bee73c95b8ed1248a4e5e113690e"))
(when (featurep! +childframe)
(package! posframe))
(package! posframe :pin "093b29a53cbeda6d637ccc9ef4dfc47123e79b9e"))
(when (featurep! :lang org)
(package! helm-org))
(package! helm-org :pin "b7a18dfc17e8b933956d61d68c435eee03a96c24"))
(package! helm-descbinds :pin "b72515982396b6e336ad7beb6767e95a80fca192")

View File

@@ -1,59 +1,62 @@
;;; completion/ido/config.el -*- lexical-binding: t; -*-
(defun +ido-init-h ()
(setq ido-ignore-buffers
'("\\` " "^\\*ESS\\*" "^\\*Messages\\*" "^\\*Help\\*" "^\\*Buffer"
"^\\*.*Completions\\*$" "^\\*Ediff" "^\\*tramp" "^\\*cvs-"
"_region_" " output\\*$" "^TAGS$" "^\*Ido")
ido-use-faces nil
ido-confirm-unique-completion t
ido-case-fold t
ido-enable-tramp-completion nil
ido-enable-flex-matching t
ido-create-new-buffer 'always
ido-enable-tramp-completion t
ido-enable-last-directory-history t
ido-save-directory-list-file (concat doom-cache-dir "ido.last"))
(defvar ido-mode-hook nil
"List of hooks to run when `ido-mode' is activated.")
(unless (member "\\`.DS_Store$" ido-ignore-files)
(push "\\`.DS_Store$" ido-ignore-files)
(push "Icon\\?$" ido-ignore-files))
(define-key! (ido-common-completion-map ido-completion-map ido-file-completion-map)
"\C-n" #'ido-next-match
"\C-p" #'ido-prev-match
"\C-w" #'ido-delete-backward-word-updir
;; Go to $HOME with ~
"~" (λ! (if (looking-back "/" (point-min))
(insert "~/")
(call-interactively #'self-insert-command))))
(defadvice! +ido--sort-mtime-a ()
"Sort ido filelist by mtime instead of alphabetically."
:override #'ido-sort-mtime
(setq ido-temp-list
(sort ido-temp-list
(lambda (a b)
(time-less-p
(sixth (file-attributes (concat ido-current-directory b)))
(sixth (file-attributes (concat ido-current-directory a)))))))
(ido-to-end ;; move . files to end (again)
(cl-loop for x in ido-temp-list
if (char-equal (string-to-char x) ?.)
collect x)))
(add-hook! '(ido-make-file-list-hook ido-make-dir-list-hook)
#'ido-sort-mtime)
;;
(ido-mode 1)
(ido-everywhere 1)
(ido-ubiquitous-mode 1)
(ido-vertical-mode 1)
(flx-ido-mode +1)
(crm-custom-mode +1)
;;
(remove-hook 'ido-setup-hook #'+ido-init-h))
;;
(add-hook 'ido-setup-hook #'+ido-init-h)
;;; Packages
(use-package! ido
:hook (doom-first-input . ido-mode)
:hook (ido-mode . ido-everywhere)
:hook (ido-mode . ido-ubiquitous-mode)
:preface
;; HACK `ido' is a really old package. It defines `ido-mode' manually and
;; doesn't define a hook, so we define one for it, so we can use it!
(defadvice! +ido-run-hooks-a (&rest _)
:after #'ido-mode
(run-hooks 'ido-mode-hook))
:init
(setq ido-save-directory-list-file (concat doom-cache-dir "ido.last"))
:config
(pushnew! ido-ignore-files "\\`.DS_Store$" "Icon\\?$")
(setq ido-ignore-buffers
'("\\` " "^\\*ESS\\*" "^\\*Messages\\*" "^\\*[Hh]elp" "^\\*Buffer"
"^\\*.*Completions\\*$" "^\\*Ediff" "^\\*tramp" "^\\*cvs-" "_region_"
" output\\*$" "^TAGS$" "^\*Ido")
ido-auto-merge-work-directories-length -1
ido-confirm-unique-completion t
ido-case-fold t
ido-create-new-buffer 'always
ido-enable-flex-matching t)
(map! :map (ido-common-completion-map ido-file-completion-map)
"C-w" #'ido-delete-backward-word-updir
:map (ido-common-completion-map ido-file-dir-completion-map)
"C-n" #'ido-next-match
"C-p" #'ido-prev-match
[down] #'ido-next-match
[up] #'ido-prev-match
:map ido-file-completion-map
;; Go to $HOME with ~
"~" (cmd! (if (looking-back "/" (point-min))
(insert "~/")
(call-interactively #'self-insert-command)))))
(use-package! ido-vertical-mode
:hook (ido-mode . ido-vertical-mode)
:config (setq ido-vertical-show-count t))
(use-package! ido-sort-mtime
:hook (ido-mode . ido-sort-mtime-mode))
(use-package! crm-custom
:hook (ido-mode . crm-custom-mode))
(use-package! flx-ido
:hook (ido-mode . flx-ido-mode))

View File

@@ -1,7 +1,8 @@
;; -*- no-byte-compile: t; -*-
;;; completion/ido/packages.el
(package! flx-ido)
(package! ido-completing-read+)
(package! ido-vertical-mode)
(package! crm-custom)
(package! flx-ido :pin "17f5c9cb2af18aa6f52910ff4a5a63591261ced5")
(package! ido-completing-read+ :pin "98d3a6e56b1d3652da7b47f49f76d77f82ea80ba")
(package! ido-sort-mtime :pin "f638ff0c922af862f5211779f2311a27fde428eb")
(package! ido-vertical-mode :pin "16c4c1a112796ee0bcf401ea39d3e2643a89feaf")
(package! crm-custom :pin "f1aaccf64306a5f99d9bf7ba815d7ea41c15518d")

View File

@@ -136,7 +136,7 @@ These keybindings are available while a search is active:
| =C-c C-o= | Open a buffer with your search results |
| =C-c C-e= | Open a writable buffer of your search results |
| =C-SPC= | Preview the current candidate |
| =M-RET= | Open the selected candidate in other-window |
| =C-RET= | Open the selected candidate in other-window |
Changes to the resulting wgrep buffer (opened by =C-c C-e=) can be committed
with =C-c C-c= and aborted with =C-c C-k= (alternatively =ZZ= and =ZQ=, for evil

View File

@@ -13,16 +13,6 @@
(and (not (eq buffer (current-buffer)))
(+workspace-contains-buffer-p buffer))))
;;;###autoload
(defun +ivy-standard-search (str)
"TODO"
(funcall +ivy-standard-search-fn str))
;;;###autoload
(defun +ivy-alternative-search (str)
"TODO"
(funcall +ivy-alternative-search-fn str))
;;;###autoload
(defun +ivy-rich-buffer-name (candidate)
"Display the buffer name.
@@ -188,7 +178,7 @@ If ARG (universal argument), open selection in other-window."
(user-error "%S doesn't support wgrep" caller)))))
;;;###autoload
(defun +ivy-yas-prompt (prompt choices &optional display-fn)
(defun +ivy-yas-prompt-fn (prompt choices &optional display-fn)
(yas-completing-prompt prompt choices display-fn #'ivy-completing-read))
;;;###autoload
@@ -217,28 +207,33 @@ If ARG (universal argument), open selection in other-window."
;;;###autoload
(defun +ivy/projectile-find-file ()
"A more sensible `counsel-projectile-find-file', which will revert to
`counsel-find-file' if invoked from $HOME, `counsel-file-jump' if invoked from a
non-project, `projectile-find-file' if in a big project (more than
`counsel-find-file' if invoked from $HOME or /, `counsel-file-jump' if invoked
from a non-project, `projectile-find-file' if in a big project (more than
`ivy-sort-max-size' files), or `counsel-projectile-find-file' otherwise.
The point of this is to avoid Emacs locking up indexing massive file trees."
(interactive)
(call-interactively
(cond ((or (file-equal-p default-directory "~")
(when-let (proot (doom-project-root))
(file-equal-p proot "~")))
#'counsel-find-file)
;; Spoof the command so that ivy/counsel will display the (well fleshed-out)
;; actions list for `counsel-find-file' on C-o. The actions list for the other
;; commands aren't as well configured or are empty.
(let ((this-command 'counsel-find-file))
(call-interactively
(cond ((or (file-equal-p default-directory "~")
(file-equal-p default-directory "/")
(when-let (proot (doom-project-root))
(file-equal-p proot "~")))
#'counsel-find-file)
((doom-project-p)
(let ((files (projectile-current-project-files)))
(if (<= (length files) ivy-sort-max-size)
#'counsel-projectile-find-file
#'projectile-find-file)))
((doom-project-p)
(let ((files (projectile-current-project-files)))
(if (<= (length files) ivy-sort-max-size)
#'counsel-projectile-find-file
#'projectile-find-file)))
(#'counsel-file-jump))))
(#'counsel-file-jump)))))
;;;###autoload
(cl-defun +ivy-file-search (&key query in all-files (recursive t))
(cl-defun +ivy-file-search (&key query in all-files (recursive t) prompt args)
"Conduct a file search using ripgrep.
:query STRING
@@ -252,36 +247,34 @@ The point of this is to avoid Emacs locking up indexing massive file trees."
(unless (executable-find "rg")
(user-error "Couldn't find ripgrep in your PATH"))
(require 'counsel)
(let* ((ivy-more-chars-alist '((t . 1)))
(let* ((this-command 'counsel-rg)
(project-root (or (doom-project-root) default-directory))
(directory (or in project-root))
(default-directory directory)
(args (concat (if all-files " -uu")
(unless recursive " --maxdepth 1"))))
(unless recursive " --maxdepth 1")
" " (mapconcat #'shell-quote-argument args " "))))
(setq deactivate-mark t)
(counsel-rg
(or (if query query)
(when (use-region-p)
(let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))
(end (or (bound-and-true-p evil-visual-end) (region-end))))
(when (> (abs (- end beg)) 1)
(let ((query (buffer-substring-no-properties beg end)))
;; Escape characters that are special to ivy searches
(replace-regexp-in-string "[! |]" (lambda (substr)
(cond ((and (string= substr " ")
(not (featurep! +fuzzy)))
" ")
((string= substr "|")
"\\\\\\\\|")
((concat "\\\\" substr))))
(rxt-quote-pcre query)))))))
(or query
(when (doom-region-active-p)
(replace-regexp-in-string
"[! |]" (lambda (substr)
(cond ((and (string= substr " ")
(not (featurep! +fuzzy)))
" ")
((string= substr "|")
"\\\\\\\\|")
((concat "\\\\" substr))))
(rxt-quote-pcre (doom-thing-at-point-or-region)))))
directory args
(format "rg%s %s"
args
(cond ((equal directory default-directory)
"./")
((equal directory project-root)
(projectile-project-name))
((file-relative-name directory project-root)))))))
(or prompt
(format "rg%s [%s]: "
args
(cond ((equal directory default-directory)
"./")
((equal directory project-root)
(projectile-project-name))
((file-relative-name directory project-root))))))))
;;;###autoload
(defun +ivy/project-search (&optional arg initial-query directory)

View File

@@ -14,33 +14,31 @@ When 'everything, also preview virtual buffers")
"A plist mapping ivy/counsel commands to commands that generate an editable
results buffer.")
(defvar +ivy-standard-search-fn
(if (featurep! +prescient)
#'+ivy-prescient-non-fuzzy
#'ivy--regex-plus)
"Function to use for non-fuzzy search commands.
This uses the standard search algorithm ivy uses (or a variant of it).")
(defvar +ivy-alternative-search-fn
(cond ((featurep! +prescient) #'ivy-prescient-re-builder)
((featurep! +fuzzy) #'ivy--regex-fuzzy)
;; Ignore order for non-fuzzy searches by default
(#'ivy--regex-ignore-order))
"Function to use for fuzzy search commands.
This uses a search algorithm other than ivy's default.")
;;
;;; Packages
(use-package! ivy
:after-call pre-command-hook
:hook (doom-first-input . ivy-mode)
:init
(setq ivy-re-builders-alist
`((counsel-rg . +ivy-standard-search)
(swiper . +ivy-standard-search)
(swiper-isearch . +ivy-standard-search)
(t . +ivy-alternative-search)))
(let ((standard-search-fn
(if (featurep! +prescient)
#'+ivy-prescient-non-fuzzy
#'ivy--regex-plus))
(alt-search-fn
(if (featurep! +fuzzy)
#'ivy--regex-fuzzy
;; Ignore order for non-fuzzy searches by default
#'ivy--regex-ignore-order)))
(setq ivy-re-builders-alist
`((counsel-rg . ,standard-search-fn)
(swiper . ,standard-search-fn)
(swiper-isearch . ,standard-search-fn)
(t . ,alt-search-fn))
ivy-more-chars-alist
'((counsel-rg . 1)
(counsel-search . 2)
(t . 3))))
(define-key!
[remap switch-to-buffer] #'+ivy/switch-buffer
@@ -90,7 +88,7 @@ This uses a search algorithm other than ivy's default.")
(setq +ivy--origin nil)))
(after! yasnippet
(add-hook 'yas-prompt-functions #'+ivy-yas-prompt))
(add-hook 'yas-prompt-functions #'+ivy-yas-prompt-fn))
(defadvice! +ivy--inhibit-completion-in-region-a (orig-fn &rest args)
"`ivy-completion-in-region' struggles with completing certain
@@ -99,19 +97,11 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(let ((completion-in-region-function #'completion--in-region))
(apply orig-fn args)))
(define-key ivy-minibuffer-map (kbd "C-c C-e") #'+ivy/woccur)
(ivy-mode +1)
(use-package! ivy-hydra
:commands (ivy-dispatching-done ivy--matcher-desc ivy-hydra/body)
:init
(define-key! ivy-minibuffer-map
"C-o" #'ivy-dispatching-done
"M-o" #'hydra-ivy/body)
:config
;; ivy-hydra rebinds this, so we have to do so again
(define-key ivy-minibuffer-map (kbd "M-o") #'hydra-ivy/body)))
(define-key! ivy-minibuffer-map
[remap doom/delete-backward-word] #'ivy-backward-kill-word
"C-c C-e" #'+ivy/woccur
"C-o" #'ivy-dispatching-done
"M-o" #'hydra-ivy/body))
(use-package! ivy-rich
@@ -122,15 +112,27 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(when (featurep! +icons)
(cl-pushnew '(+ivy-rich-buffer-icon)
(cadr (plist-get ivy-rich-display-transformers-list
'ivy-switch-buffer))))
'ivy-switch-buffer))
:test #'equal))
;; Include variable value in `counsel-describe-variable'
;; Enahnce the appearance of a couple counsel commands
(plist-put! ivy-rich-display-transformers-list
'counsel-describe-variable
'(:columns
((counsel-describe-variable-transformer (:width 40)) ; the original transformer
(+ivy-rich-describe-variable-transformer (:width 50))
(ivy-rich-counsel-variable-docstring (:face font-lock-doc-face)))))
(+ivy-rich-describe-variable-transformer (:width 50)) ; display variable value
(ivy-rich-counsel-variable-docstring (:face font-lock-doc-face))))
'counsel-M-x
'(:columns
((counsel-M-x-transformer (:width 60))
(ivy-rich-counsel-function-docstring (:face font-lock-doc-face))))
;; Apply switch buffer transformers to `counsel-projectile-switch-to-buffer' as well
'counsel-projectile-switch-to-buffer
(plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer)
'counsel-bookmark
'(:columns
((ivy-rich-candidate (:width 0.5))
(ivy-rich-bookmark-filename (:width 60)))))
;; Remove built-in coloring of buffer list; we do our own
(setq ivy-switch-buffer-faces-alist nil)
@@ -138,15 +140,9 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
;; Highlight buffers differently based on whether they're in the same project
;; as the current project or not.
(let* ((plist (plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer))
(switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns))))
(when switch-buffer-alist
(setcar switch-buffer-alist '+ivy-rich-buffer-name)))
;; Apply switch buffer transformers to `counsel-projectile-switch-to-buffer' as well
(plist-put! ivy-rich-display-transformers-list
'counsel-projectile-switch-to-buffer
(plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer))
(when-let* ((plist (plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer))
(switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns))))
(setcar switch-buffer-alist '+ivy-rich-buffer-name))
(ivy-rich-mode +1))
@@ -161,9 +157,10 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(all-the-icons-ivy-setup)
(after! counsel-projectile
(let ((all-the-icons-ivy-file-commands '(counsel-projectile
counsel-projectile-find-file
counsel-projectile-find-dir)))
(let ((all-the-icons-ivy-file-commands
'(counsel-projectile
counsel-projectile-find-file
counsel-projectile-find-dir)))
(all-the-icons-ivy-setup))))
@@ -173,62 +170,69 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(define-key!
[remap apropos] #'counsel-apropos
[remap bookmark-jump] #'counsel-bookmark
[remap compile] #'+ivy/compile
[remap describe-bindings] #'counsel-descbinds
[remap describe-face] #'counsel-faces
[remap describe-function] #'counsel-describe-function
[remap describe-variable] #'counsel-describe-variable
[remap describe-bindings] #'counsel-descbinds
[remap set-variable] #'counsel-set-variable
[remap evil-ex-registers] #'counsel-evil-registers
[remap evil-show-marks] #'counsel-mark-ring
[remap execute-extended-command] #'counsel-M-x
[remap find-file] #'counsel-find-file
[remap find-library] #'counsel-find-library
[remap info-lookup-symbol] #'counsel-info-lookup-symbol
[remap imenu] #'counsel-imenu
[remap recentf-open-files] #'counsel-recentf
[remap swiper] #'counsel-grep-or-swiper
[remap evil-ex-registers] #'counsel-evil-registers
[remap evil-show-marks] #'counsel-mark-ring
[remap yank-pop] #'counsel-yank-pop
[remap info-lookup-symbol] #'counsel-info-lookup-symbol
[remap load-theme] #'counsel-load-theme
[remap locate] #'counsel-locate
[remap org-goto] #'counsel-org-goto
[remap org-set-tags-command] #'counsel-org-tag
[remap projectile-compile-project] #'+ivy/project-compile
[remap recentf-open-files] #'counsel-recentf
[remap set-variable] #'counsel-set-variable
[remap swiper] #'counsel-grep-or-swiper
[remap unicode-chars-list-chars] #'counsel-unicode-char
[remap compile] #'+ivy/compile
[remap projectile-compile-project] #'+ivy/project-compile)
[remap yank-pop] #'counsel-yank-pop)
:config
(set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil)
;; HACK Fix an issue where `counsel-projectile-find-file-action' would try to
;; open a candidate in an occur buffer relative to the wrong buffer,
;; causing it to fail to find the file we want.
(defadvice! +ivy--run-from-ivy-directory-a (orig-fn &rest args)
:around #'counsel-projectile-find-file-action
(let ((default-directory (ivy-state-directory ivy-last)))
(apply orig-fn args)))
;; Don't use ^ as initial input. Set this here because `counsel' defines more
;; of its own, on top of the defaults.
(setq ivy-initial-inputs-alist nil)
;; REVIEW Move this somewhere else and perhaps generalize this so both
;; ivy/helm users can enjoy it.
(defadvice! +ivy--counsel-file-jump-use-fd-rg-a (args)
"Change `counsel-file-jump' to use fd or ripgrep, if they are available."
:override #'counsel--find-return-list
(cl-destructuring-bind (find-program . args)
(cond ((executable-find "fd")
(cons "fd" (list "-t" "f" "-E" ".git")))
((executable-find "rg")
(cons "rg" (list "--files" "--hidden" "--no-messages")))
((cons find-program args)))
(unless (listp args)
(user-error "`counsel-file-jump-args' is a list now, please customize accordingly."))
(counsel--call
(cons find-program args)
(lambda ()
(goto-char (point-min))
(let ((offset (if (member find-program '("fd" "rg")) 0 2))
files)
(while (< (point) (point-max))
(push (buffer-substring
(+ offset (line-beginning-position)) (line-end-position)) files)
(forward-line 1))
(nreverse files))))))
;; REVIEW Counsel allows `counsel-rg-base-command' to be a string or list.
;; This backwards compatibility complicates things for Doom. Simpler to
;; just force it to always be a list.
(when (stringp counsel-rg-base-command)
(setq counsel-rg-base-command (split-string counsel-rg-base-command)))
;; REVIEW Fix #3215: prevents mingw on Windows throwing an error trying to
;; expand / to an absolute path. Remove this when it is fixed upstream
;; in counsel.
(when (and (memq system-type '(windows-nt ms-dos))
(listp counsel-rg-base-command)
(member "--path-separator" counsel-rg-base-command))
(setf (cadr (member "--path-separator" counsel-rg-base-command))
"//"))
;; Integrate with `helpful'
(setq counsel-describe-function-function #'helpful-callable
counsel-describe-variable-function #'helpful-variable)
;; Record in jumplist when opening files via counsel-{ag,rg,pt,git-grep}
(add-hook 'counsel-grep-post-action-hook #'better-jumper-set-jump)
(add-hook 'counsel-grep-post-action-hook #'recenter)
(ivy-add-actions
'counsel-rg ; also applies to `counsel-rg'
'(("O" +ivy-git-grep-other-window-action "open in other window")))
;; Make `counsel-compile' projectile-aware (if you prefer it over
;; `+ivy/compile' and `+ivy/project-compile')
(add-to-list 'counsel-compile-root-functions #'projectile-project-root)
@@ -236,33 +240,69 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
;; Persist `counsel-compile' history
(add-to-list 'savehist-additional-variables 'counsel-compile-history))
;; Use spotlight on mac for `counsel-locate' by default, since it doesn't need
;; any additional setup.
;; `counsel-imenu' -- no sorting for imenu. Sort it by appearance in page.
(add-to-list 'ivy-sort-functions-alist '(counsel-imenu))
;; `counsel-locate'
(when IS-MAC
;; Use spotlight on mac by default since it doesn't need any additional setup
(setq counsel-locate-cmd #'counsel-locate-cmd-mdfind))
;; `swiper'
;; Don't mess with font-locking on the dashboard; it causes breakages
(add-to-list 'swiper-font-lock-exclude #'+doom-dashboard-mode)
;; Record in jumplist when opening files via counsel-{ag,rg,pt,git-grep}
(add-hook 'counsel-grep-post-action-hook #'better-jumper-set-jump)
;; Configure `counsel-find-file'
;; `counsel-find-file'
(setq counsel-find-file-ignore-regexp "\\(?:^[#.]\\)\\|\\(?:[#~]$\\)\\|\\(?:^Icon?\\)")
(ivy-add-actions
'counsel-find-file
'(("p" (lambda (path) (with-ivy-window (insert (file-relative-name path default-directory))))
"insert relative path")
("P" (lambda (path) (with-ivy-window (insert path)))
"insert absolute path")
("l" (lambda (path) (with-ivy-window (insert (format "[[./%s]]" (file-relative-name path default-directory)))))
"insert relative org-link")
("L" (lambda (path) (with-ivy-window (insert (format "[[%s]]" path))))
"Insert absolute org-link")))
(dolist (fn '(counsel-rg counsel-find-file))
(ivy-add-actions
fn '(("p" (lambda (path) (with-ivy-window (insert (file-relative-name path default-directory))))
"insert relative path")
("P" (lambda (path) (with-ivy-window (insert path)))
"insert absolute path")
("l" (lambda (path) (with-ivy-window (insert (format "[[./%s]]" (file-relative-name path default-directory)))))
"insert relative org-link")
("L" (lambda (path) (with-ivy-window (insert (format "[[%s]]" path))))
"Insert absolute org-link"))))
(ivy-add-actions
'counsel-ag ; also applies to `counsel-rg'
'(("O" +ivy-git-grep-other-window-action "open in other window"))))
(ivy-add-actions 'counsel-file-jump (plist-get ivy--actions-list 'counsel-find-file))
;; `counsel-search': use normal page for displaying results, so that we see
;; custom ddg themes (if one is set).
(setf (nth 1 (alist-get 'ddg counsel-search-engines-alist))
"https://duckduckgo.com/?q=")
;; REVIEW Move this somewhere else and perhaps generalize this so both
;; ivy/helm users can enjoy it.
(defadvice! +ivy--counsel-file-jump-use-fd-rg-a (args)
"Change `counsel-file-jump' to use fd or ripgrep, if they are available."
:override #'counsel--find-return-list
(cl-destructuring-bind (find-program . args)
(cond ((executable-find doom-projectile-fd-binary)
(append (list doom-projectile-fd-binary
"--color=never" "-E" ".git"
"--type" "file" "--type" "symlink" "--follow")
(if IS-WINDOWS '("--path-separator=/"))))
((executable-find "rg")
(append (list "rg" "--files" "--follow" "--color=never" "--hidden" "--no-messages")
(cl-loop for dir in projectile-globally-ignored-directories
collect "--glob"
collect (concat "!" dir))
(if IS-WINDOWS (list "--path-separator" "/"))))
((cons find-program args)))
(unless (listp args)
(user-error "`counsel-file-jump-args' is a list now, please customize accordingly."))
(counsel--call
(cons find-program args)
(lambda ()
(goto-char (point-min))
(let ((offset (if (member find-program (list "rg" doom-projectile-fd-binary)) 0 2))
files)
(while (< (point) (point-max))
(push (buffer-substring (+ offset (line-beginning-position)) (line-end-position))
files)
(forward-line 1))
(nreverse files)))))))
(use-package! counsel-projectile
@@ -284,7 +324,10 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
#'+ivy/projectile-find-file)
;; no highlighting visited files; slows down the filtering
(ivy-set-display-transformer #'counsel-projectile-find-file nil))
(ivy-set-display-transformer #'counsel-projectile-find-file nil)
(when (featurep! +prescient)
(setq counsel-projectile-sort-files t)))
(use-package! wgrep
@@ -311,7 +354,9 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
;; posframe.
(dolist (fn '(swiper counsel-rg counsel-grep counsel-git-grep))
(setf (alist-get fn ivy-posframe-display-functions-alist)
#'ivy-display-function-fallback)))
#'ivy-display-function-fallback))
(add-hook 'doom-reload-hook #'posframe-delete-all))
(use-package! flx
@@ -322,24 +367,26 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(use-package! ivy-prescient
:hook (ivy-mode . ivy-prescient-mode)
:when (featurep! +prescient)
:hook (ivy-mode . ivy-prescient-mode)
:hook (ivy-prescient-mode . prescient-persist-mode)
:init
(setq prescient-filter-method
(if (featurep! +fuzzy)
'(literal regexp initialism fuzzy)
'(literal regexp initialism))
ivy-prescient-enable-filtering nil ; we do this ourselves
ivy-prescient-retain-classic-highlighting t)
'(literal regexp initialism)))
:config
(setq ivy-prescient-sort-commands
'(:not swiper swiper-isearch ivy-switch-buffer counsel-grep
counsel-git-grep counsel-ag counsel-rg counsel-imenu
counsel-yank-pop counsel-recentf counsel-buffer-or-recentf)
ivy-prescient-retain-classic-highlighting t)
(defun +ivy-prescient-non-fuzzy (str)
(let ((prescient-filter-method '(literal regexp)))
(ivy-prescient-re-builder str)))
;; NOTE prescient config duplicated with `company'
(setq prescient-save-file (concat doom-cache-dir "prescient-save.el"))
(prescient-persist-mode +1))
(setq prescient-save-file (concat doom-cache-dir "prescient-save.el")))
;;;###package swiper

View File

@@ -1,22 +1,23 @@
;; -*- no-byte-compile: t; -*-
;;; completion/ivy/packages.el
(package! amx)
(package! swiper :pin "544e7de63a4543a74596c5d95efa0bb9da25791e")
(package! ivy)
(package! counsel)
(package! counsel-projectile)
(package! swiper)
(package! ivy-hydra)
(package! ivy-rich)
(package! wgrep)
(package! counsel)
(package! amx :pin "7fb7b874291e0cdeb1f0acb18564a686ec86788d")
(package! counsel-projectile :pin "77392cbbc42e98fc137b43f1db1b111ba6e2dd75")
(package! ivy-rich :pin "10970130b41c6ef9570893cdab8dfbe720e2b1a9")
(package! wgrep :pin "f0ef9bfa44db503cdb2f83fcfbd2fa4e2382ef1f")
(if (featurep! +prescient)
(package! ivy-prescient)
(package! ivy-prescient :pin "3ab7605d997fb8337bf5ded2ad960b98ac0e1fd7")
(when (featurep! +fuzzy)
(package! flx)))
(package! flx :pin "17f5c9cb2af18aa6f52910ff4a5a63591261ced5")))
(when (featurep! +childframe)
(package! ivy-posframe))
(package! ivy-posframe :pin "44749562a9e68bd43ccaa225b31311476fab1251"))
(when (featurep! +icons)
(package! all-the-icons-ivy))
(package! all-the-icons-ivy :pin "a70cbfa1effe36efc946a823a580cec686d5e88d"))