;;; -*- lexical-binding: t -*- ;; Time-stamp: <2026-08-25 15h27 BST (581d7bf5)> (use-package savehist :ensure t :init (savehist-mode)) ;; ----------------------------------------------------------------------------- ;; General configuration (use-package emacs :init ;; Add prompt indicator to `completing-read-multiple'. (defun crm-indicator (args) (cons (concat "[CRM] " (car args)) (cdr args))) (advice-add #'completing-read-multiple :filter-args #'crm-indicator) ;; Grow and shrink minibuffer ;;(setq resize-mini-windows t) ;; Do not allow the cursor in the minibuffer prompt (setq minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) ;; Enable recursive minibuffers (setq enable-recursive-minibuffers t)) (use-package icomplete :hook ((after-init . (lambda () (icomplete-vertical-mode 1))) (icomplete-minibuffer-setup . (lambda () (setq truncate-lines t)))) :init (defun my-completing-read-in-region (start end collection &optional predicate) "Prompt for completion of region in the minibuffer." (barf-if-buffer-read-only) (let* ((initial (buffer-substring-no-properties start end)) (source-buffer (current-buffer)) (wrapped-table (if (functionp collection) `(lambda (str pred action) (let ((result (with-current-buffer ,source-buffer (funcall ',collection str pred action)))) (if (eq action 'metadata) (cons 'metadata (mapcar (lambda (x) (if (and (consp x) (symbolp (car x)) (string-suffix-p "-function" (symbol-name (car x))) (functionp (cdr x))) (cons (car x) `(lambda (&rest args) (with-current-buffer ,',source-buffer (apply ',(cdr x) args)))) x)) (cdr result))) result))) collection)) (exit-fn (plist-get completion-extra-properties :exit-function)) (ann-fun (plist-get completion-extra-properties :annotation-function)) (aff-fun (plist-get completion-extra-properties :affixation-function)) (completion-extra-properties `(,@(and ann-fun (list :annotation-function `(lambda (&rest args) (with-current-buffer ,source-buffer (apply ',ann-fun args))))) ,@(and aff-fun (list :affixation-function `(lambda (&rest args) (with-current-buffer ,source-buffer (apply ',aff-fun args))))))) (minibuffer-allow-text-properties t) (enable-recursive-minibuffers t) (completion (completing-read "Completion: " wrapped-table predicate t initial))) (cond ((and completion (not (string-empty-p completion))) (completion--replace start end completion) (when exit-fn (funcall exit-fn completion (if (eq (try-completion completion collection predicate) t) 'finished 'exact))) t) (t ([message]I "No completion") nil)))) (defun my-icomplete-backspace () "Delete back to previous / in paths, or normal backspace otherwise." (interactive) (if (looking-back "[^/]/" (line-beginning-position)) (let ((slash-pos (save-excursion (backward-word 1) (search-backward "/" nil t)))) (if slash-pos (delete-region (1+ slash-pos) (point)) (delete-backward-char 1))) (delete-backward-char 1))) (defun my-switch-to-buffer-with-recentf () "Switch to buffer or recent file with visual separation." (interactive) (let* ((current-buffer (buffer-name (current-buffer))) (buffers (seq-remove (lambda (b) (or (string-prefix-p " " b) (string= b current-buffer))) (mapcar #'buffer-name (buffer-list)))) (recent-files (seq-take recentf-list 20)) (separator "─── Recent Files ───") (buffer-cands (mapcar (lambda (buf) (propertize buf 'multi-category (cons 'buffer buf))) buffers)) (header-cand (propertize separator 'multi-category (cons 'separator t))) (file-cands (mapcar (lambda (file) (propertize file 'multi-category (cons 'file file))) recent-files)) (all-cands (append buffer-cands (list header-cand) file-cands)) (my-table (lambda (string pred action) (pcase action ('metadata '(metadata (category . multi-category) (cycle-sort-function . identity))) ('all all-cands) ('lambda (or (try-completion string all-cands pred) string)) (_ (seq-filter (lambda (c) (string-prefix-p string (substring-no-properties c))) all-cands)))))) (let ((result (completing-read "Switch to: " my-table nil t))) (unless (string-empty-p result) (cond ((string= result separator) nil) ((file-exists-p result) (find-file result)) (t (switch-to-buffer result))))))) :bind (("C-x b" . my-switch-to-buffer-with-recentf) (:map icomplete-minibuffer-map ("TAB" . icomplete-force-complete) ("C-j" . icomplete-ret) ("RET" . icomplete-force-complete-and-exit) ("" . my-icomplete-backspace))) :config (setq icomplete-compute-delay 0 icomplete-show-matches-on-no-input t icomplete-hide-common-prefix nil icomplete-prospects-height 10 icomplete-max-delay-chars 0 icomplete-scroll t) (setq completion-styles '(flex basic partial-completion) completion-ignore-case t) (setq completion-in-region-function #'my-completing-read-in-region)) ;; ----------------------------------------------------------------------------- ;; Marginalia (use-package marginalia :ensure t :bind (:map minibuffer-local-map ("M-A" . marginalia-cycle)) :init (marginalia-mode))