Files
emacs/settings/completion-settings.el
2025-07-04 23:58:34 +02:00

252 lines
10 KiB
EmacsLisp

;; completion-settings.el --- Completion settings -*- lexical-binding: t -*-
;;; Commentary:
;; <M-tab> alias of C-M-i
;; in general `completion-at-point' (`minibuffer.el')
;; in python-mode `anaconde-mode-complete'
;; manual https://oremacs.com/swiper/
;; org:
;; - org-insert-structure-template is bound to C-c C-,
;; - for easy-template require org-tempo or add to org-modules
;; https://orgmode.org/manual/Easy-templates.html#Easy-templates
;; Requirements:
;; amx https://melpa.org/#/?q=amx
;; ivy (instead of ido) https://elpa.gnu.org/packages/ivy.html
;; counsel https://github.com/abo-abo/swiper
;; swiper https://github.com/abo-abo/swiper
;; company https://elpa.gnu.org/packages/company.html
;; config for R see ess-settings.el
;; company-quickhelp https://github.com/company-mode/company-quickhelp
;; pos-tip
;; yasnippet
;; popup
;; yasnippet-snippets https://melpa.org/#/yasnippet-snippets
;;; Code:
(use-package amx
:commands amx
:config
(setq amx-save-file (concat user-cache-directory "amx-items")))
;; in an ivy action minibuffer use M-o (`ivy-dispatching-done') to see
;; valid actions.
(use-package ivy
:delight (ivy-mode "Ivy") ;; \u24BE i
:commands (ivy-mode)
:defer 0.1
;; Ivy-based interface to standard commands
:bind (("C-s" . swiper)
;; ("C-M-s" . swiper-all)
("C-c C-r" . ivy-resume) ;; resumes the last Ivy-based completion.
("C-c v" . ivy-push-view)
("C-c V" . ivy-pop-view))
:config
(ivy-mode 1) ;; also with `ivy-rich-mode' (see below). `ivy-mode' still active for views not defined by `ivy-rich-mode'.
(setq ivy-use-virtual-buffers t) ;; Add recent files and bookmarks to the ivy-switch-buffer
(setq ivy-count-format "%d/%d ") ;; Displays the current and total number in the collection in the prompt
(setq enable-recursive-minibuffers t)
(setq ivy-extra-directories '("../" "./")) ;; keep "./" and "../" in the list to be able to use also mouse click and if asked for directory to have the current one as a candidate "./"
(setq ivy-use-selectable-prompt t) ;; make the prompt line selectable. Example: create a file bar when a file barricade exists in the current directory. Also C-M-j usable
;; enable this if you want `swiper' to use it
;; (setq search-default-mode #'char-fold-to-regexp)
)
(use-package all-the-icons-ivy-rich
;; https://github.com/seagle0128/all-the-icons-ivy-rich
:defer
:if (display-graphic-p)
:commands (all-the-icons-ivy-rich-mode))
(use-package ivy-rich
:defer 0.1
:config
(setcdr (assq t ivy-format-functions-alist) #'ivy-format-function-line)
;; For better performance, enable all-the-icons-ivy-rich-mode before ivy-rich-mode.
(when (display-graphic-p)
(all-the-icons-ivy-rich-mode 1))
(ivy-rich-mode 1))
(use-package swiper)
(use-package counsel
:after ivy
:bind (("M-x" . counsel-M-x)
("M-y" . counsel-yank-pop)
("C-x b" . counsel-switch-buffer)
;; ("C-x b" . counsel-ibuffer)
("C-x C-f" . counsel-find-file)
;; ("C-x C-r" . counsel-recentf)
("C-x C-r" . counsel-buffer-or-recentf)
("C-h f" . counsel-describe-function)
("C-h v" . counsel-describe-variable)
("C-h o" . counsel-describe-symbol)
("C-h l" . counsel-find-library)
;; ("<f2> i" . counsel-info-lookup-symbol) ;; info-lookup-symbol see helpful-symbol
("<f2> u" . counsel-unicode-char)
("<f2> j" . counsel-set-variable)
;; Ivy-based interface to shell and system tools
("C-c c" . counsel-compile)
("C-c g" . counsel-git)
("C-c j" . counsel-git-grep)
("C-c L" . counsel-git-log)
("C-c k" . counsel-rg) ;; 'counsel-ag 'counsel-rg
("C-c m" . counsel-linux-app)
("C-c n" . counsel-fzf)
("C-x l" . counsel-locate)
("C-c J" . counsel-file-jump)
("C-S-o" . counsel-rhythmbox)
("C-c w" . counsel-wmctrl)
;; other commands
("C-c b" . counsel-bookmark)
("C-c d" . counsel-descbinds)
("C-c o" . counsel-outline)
("C-c t" . counsel-load-theme)
("C-c F" . counsel-org-file)
:map minibuffer-local-map
("C-r" . counsel-minibuffer-history))
:config
;; Do not open dired for directories when using counsel-find-file
;; https://emacs.stackexchange.com/questions/33701/do-not-open-dired-for-directories-when-using-counsel-find-file
(let ((done (where-is-internal #'ivy-done ivy-minibuffer-map t))
(alt (where-is-internal #'ivy-alt-done ivy-minibuffer-map t)))
(define-key counsel-find-file-map done #'ivy-alt-done)
(define-key counsel-find-file-map alt #'ivy-done)
(define-key counsel-find-file-map (kbd "TAB") 'ivy-alt-done)
(define-key counsel-find-file-map (kbd "<tab>") 'ivy-alt-done)
;; <left> and <right> not used to be able to navigate inside the text
;; https://oremacs.com/swiper/#file-name-completion
;; ivy-done completion for file, but opens dird mode for directories
;; ivy-alt-done complete dir or open file, but without entering any character it opens dird mode
;; ivy-immediate-done no completion
)
;; previously defined in tmm.el (removed by commit on Oct 24, 2020)
;; counsel-tmm uses `tmm-get-keybind'
(defun tmm-get-keybind (keyseq)
"Return the current binding of KEYSEQ, merging prefix definitions.
If KEYSEQ is a prefix key that has local and global bindings,
we merge them into a single keymap which shows the proper order of the menu.
However, for the menu bar itself, the value does not take account
of `menu-bar-final-items'."
(lookup-key (cons 'keymap (nreverse (current-active-maps))) keyseq))
)
;;(setq tab-always-indent 'complete) ;; use 'complete when auto-complete is disabled
(use-package company
:delight (company-mode "Co") ;; \u24B8 c
;;:bind (("C-M-i" . company-complete))
:bind (([remap completion-at-point] . company-complete)
:map lisp-interaction-mode-map
("M-?" . (lambda () (interactive) (describe-symbol (symbol-at-point))))
:map emacs-lisp-mode-map
("M-?" . (lambda () (interactive) (describe-symbol (symbol-at-point)))))
;; see org bind below
:hook ((after-init . global-company-mode)
(minibuffer-setup . company-mode)) ;; minibuffer-setup-hook
:config
(setq company-idle-delay nil) ;; no idle completion, invoke with <M-tab>
(setq company-minimum-prefix-length 2)
(setq company-require-match nil)
(setq company-dabbrev-ignore-case nil)
(setq company-dabbrev-downcase nil)
;; https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Bcompletion/auto-completion
(defvar my-completion-menu-tab-key-behavior 'cycle
"What the TAB key should do when completion menu is active.
Possible values are `complete', `cycle' or nil.")
(setq my-completion-tab-key-behavior 'complete)
(defun my-completion-menu-set-tab-key-behavior (package)
"Bind TAB key appropriately for the given PACKAGE and value of
`my-completion-menu-tab-key-behavior'.
Possible PACKAGE values are `company'."
(cond
((eq 'company package)
(let ((map company-active-map))
(cond
((eq 'complete my-completion-menu-tab-key-behavior)
(define-key map (kbd "TAB") 'company-complete-selection)
(define-key map (kbd "<tab>") 'company-complete-selection))
((eq 'cycle my-completion-menu-tab-key-behavior)
(define-key map (kbd "TAB") 'company-complete-common-or-cycle)
(define-key map (kbd "<tab>") 'company-complete-common-or-cycle)
(define-key map (kbd "<S-tab>")
(lambda () (company-complete-common-or-cycle -1)))
(define-key map (kbd "<backtab>")
(lambda () (company-complete-common-or-cycle -1)))
)
(t
(define-key map (kbd "TAB") nil)
(define-key map (kbd "<tab>") nil)))))
(t (message "Not yet implemented for package %S" package))))
(my-completion-menu-set-tab-key-behavior 'company)
(with-eval-after-load 'org
(define-key org-mode-map [remap complete-symbol] 'company-complete)))
;; org completion with pcomplete company-capf
(defun my-org-mode-completion-hook ()
(add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t))
(add-hook 'org-mode-hook #'my-org-mode-completion-hook)
(use-package company-quickhelp
:after company
:bind (:map company-active-map
("C-c h" . company-quickhelp-manual-begin)) ;; manually trigger the help popup, but only when company is doing its thing.
;;:config
;;(company-quickhelp-mode 1) ;; deactivated bc/ auto show is not good
)
(use-package yasnippet ;; https://elpa.gnu.org/packages/yasnippet.html
:delight (yas-minor-mode "Ys") ;; \u24CE y
:hook ((prog-mode . yas-minor-mode)
(org-mode . yas-minor-mode))
;; see also variable yas-snippet-dirs, the yasnippet-snippets
;; collection dir is added via require 'yasnippet-snipets
:config
(define-key yas-minor-mode-map (kbd "C-c & C-s") nil)
(define-key yas-minor-mode-map (kbd "C-c & C-n") nil)
(define-key yas-minor-mode-map (kbd "C-c & C-v") nil)
(define-key yas-minor-mode-map (kbd "C-c &") nil)
(setq yas-snippet-dirs (list (concat config-dir "snippets")))
;; global
;;(yas-global-mode 1)
;; on a per-buffer basis
(yas-reload-all))
;; use popup menu for yas-choose-value
(use-package popup
:after yasnippet
:bind (:map popup-menu-keymap ;; add some shotcuts in popup menu mode
("M-n" . popup-next)
("TAB" . popup-next)
("<tab>" . popup-next)
("<backtab>" . popup-previous)
("M-p" . popup-previous))
:config
(defun yas-popup-isearch-prompt (prompt choices &optional display-fn)
(when (featurep 'popup)
(popup-menu*
(mapcar
(lambda (choice)
(popup-make-item
(or (and display-fn (funcall display-fn choice))
choice)
:value choice))
choices)
:prompt prompt
;; start isearch mode immediately
:isearch t
)))
(setq yas-prompt-functions
'(yas-popup-isearch-prompt yas-maybe-ido-prompt yas-completing-prompt yas-no-prompt)))
(use-package yasnippet-snippets
:after (yasnippet)
:defer 1)
(provide 'completion-settings)
;;; completion-settings.el ends here