Created
March 25, 2022 09:54
-
-
Save rougier/126e358464e12aa28fac5b4f3dd5eb9c to your computer and use it in GitHub Desktop.
Minibuffer frame for Nano Emacs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Nicolas .P Rougier emacs configuration - mini-frame configuration | |
;; --------------------------------------------------------------------- | |
(require 'vertico) | |
(require 'marginalia) | |
(require 'mini-frame) | |
(defun minibuffer-setup () | |
;; This prevents the header line to spill over second line | |
(let ((inhibit-message t)) | |
(toggle-truncate-lines 1)) | |
(setq enable-recursive-minibuffers t) | |
;; This allows to have a consistent full width (fake) header like | |
(setq display-table (make-display-table)) | |
(set-display-table-slot display-table | |
'truncation (make-glyph-code ?\ 'nano-subtle)) | |
(set-display-table-slot display-table | |
'wrap (make-glyph-code ?\ 'nano-subtle)) | |
(setq buffer-display-table display-table) | |
(cursor-intangible-mode) | |
(face-remap-add-relative 'default :foreground "black") | |
(face-remap-add-relative 'completions-first-difference :foreground "black") | |
(let* ((left (concat (propertize " " | |
'face '(nano-subtle) | |
'display '(raise +0.20)) | |
(propertize " Minibuffer" | |
'face 'nano-subtle) | |
(propertize " " | |
'face 'nano-subtle | |
'display '(raise -0.30)))) | |
(right (propertize "C-g: abort" | |
'face '(:inherit (nano-faded nano-subtle) | |
:weight light))) | |
(spacer (propertize (make-string (- (window-width) | |
(length left) | |
(length right) | |
1) ?\ ) | |
'face 'nano-subtle)) | |
(header (concat left spacer right " ")) | |
(overlay (make-overlay (+ (point-min) 0) (+ (point-min) 0)))) | |
(overlay-put overlay 'before-string | |
(concat | |
(propertize " " 'display header) | |
"\n" | |
;; This provides a vertical gap (half a line) above the prompt. | |
(propertize " " 'face `(:extend t) | |
'display '(raise .33) | |
'read-only t 'cursor-intangible t))))) | |
(add-hook 'minibuffer-setup-hook #'minibuffer-setup) | |
;; (defun minibuffer-exit ()) | |
;; (add-hook 'minibuffer-exit-hook #'minibuffer-exit) | |
;; Prefix/Affix the current candidate. From | |
;; https://github.com/minad/vertico/wiki#prefix-current-candidate-with-arrow | |
(defun minibuffer-format-candidate (orig cand prefix suffix index _start) | |
(let ((prefix (if (= vertico--index index) | |
" " " "))) | |
(funcall orig cand prefix suffix index _start))) | |
(advice-add #'vertico--format-candidate | |
:around #'minibuffer-format-candidate) | |
(with-eval-after-load 'vertico | |
(setq completion-styles '(basic substring partial-completion flex)) | |
(setq vertico-count 10) | |
(setq vertico-count-format nil) | |
(setq vertico-grid-separator | |
#(" | " 2 3 (display (space :width (1)) | |
face (:background "#ECEFF1")))) | |
(define-key vertico-map (kbd "<backtab>") #'minibuffer-complete) | |
(set-face-attribute 'vertico-current nil | |
:inherit '(nano-strong nano-subtle)) | |
(set-face-attribute 'completions-first-difference nil | |
:inherit '(nano-default)) | |
(set-face-attribute 'minibuffer-prompt nil | |
:inherit '(nano-default nano-strong)) | |
(setq minibuffer-prompt-properties | |
'(read-only t cursor-intangible t face minibuffer-prompt)) | |
(defun vertico--prompt-selection () | |
"Highlight the prompt" | |
(let ((inhibit-modification-hooks t)) | |
(set-text-properties (minibuffer-prompt-end) (point-max) | |
'(face (nano-strong nano-salient)))))) | |
(with-eval-after-load 'marginalia | |
(setq truncate-string-ellipsis "…") | |
(setq marginalia--ellipsis "…") | |
(setq marginalia-align 'right) | |
(setq marginalia-align-offset -1)) | |
(with-eval-after-load 'mini-frame | |
(set-face-background 'child-frame-border (face-foreground 'nano-faded)) | |
(setq mini-frame-default-height vertico-count) | |
(setq mini-frame-create-lazy t) | |
(setq mini-frame-show-parameters 'mini-frame-dynamic-parameters) | |
(setq mini-frame-ignore-commands | |
'("edebug-eval-expression" debugger-eval-expression)) | |
(setq mini-frame-internal-border-color (face-foreground 'nano-subtle-i)) | |
;; (setq mini-frame-resize 'grow-only) ;; -> buggy as of 01/05/2021 | |
;; (setq mini-frame-resize 'not-set) | |
;; (setq mini-frame-resize nil) | |
(setq mini-frame-resize t) | |
(setq mini-frame-resize-min-height 3) | |
(defun mini-frame-dynamic-parameters () | |
(let* ((edges (window-pixel-edges)) ;; (left top right bottom) | |
(body-edges (window-body-pixel-edges)) ;; (left top right bottom) | |
(left (nth 0 edges)) ;; Take margins into account | |
(top (nth 1 edges)) ;; Drop header line | |
(right (nth 2 edges)) ;; Take margins into account | |
(bottom (nth 3 body-edges)) ;; Drop header line | |
(left (if (eq left-fringe-width 0) | |
left | |
(- left (frame-parameter nil 'left-fringe)))) | |
(right (nth 2 edges)) | |
(right (if (eq right-fringe-width 0) | |
right | |
(+ right (frame-parameter nil 'right-fringe)))) | |
(fringe-left 0) | |
(fringe-right 0) | |
(border 1) | |
;; (width (- (frame-pixel-width) (* 2 (+ fringe border)))) | |
(width (- right left fringe-left fringe-right (* 0 border))) | |
(y (- top border))) | |
`((left . ,(- left border)) | |
(top . ,y) | |
(alpha . 1.0) | |
(width . (text-pixels . ,width)) | |
(left-fringe . ,fringe-left) | |
(right-fringe . ,fringe-right) | |
(child-frame-border-width . ,border) | |
(internal-border-width . ,border) | |
(foreground-color . ,(face-foreground 'nano-default)) | |
(background-color . ,(face-background 'highlight))))) | |
) | |
(vertico-mode) | |
(marginalia-mode) | |
(mini-frame-mode t) | |
(provide 'nano-minibuffer) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello @minad,
Using your vertico-buffer.el and a whittled-down version of your code snippet above, I have a working vertico that displays in a true top side-window:
First: You may notice that I have commented out two dolist forms in your my-vertico-buffer-setup. In my setup, vertico-buffer still operates as expected. Can you explain under what circumstances these dolist forms are necessary?
Second: I have to say that, even though, as you know, this implementation handles only vertico, I absolutely love it.
This is precisely the minibuffer user experience I have craved for years. Earlier in this thread, you wrote:
Could I prevail upon you to provide such a generalized "code snippet"?