From 951df9586d5a4ec4876c6fa0a6cfd79da1f26a8a Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Sat, 24 Feb 2018 13:44:15 +0100 Subject: helm: Change insert-state cursor and show visual selection in header line --- evil-collection-helm.el | 76 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/evil-collection-helm.el b/evil-collection-helm.el index 0d7cff9..5f0f286 100644 --- a/evil-collection-helm.el +++ b/evil-collection-helm.el @@ -42,8 +42,76 @@ (defvar helm-find-files-map) (defvar helm-read-file-map) +;; From https://github.com/emacs-helm/helm/issues/362. +;; Also see https://emacs.stackexchange.com/questions/17058/change-cursor-type-in-helm-header-line#17097. +;; TODO: With Evil, the cursor type is not right in the header line and the evil +;; cursor remains in the minibuffer. Visual selections also reveal overlayed +;; text. +(defun evil-collection-helm-hide-minibuffer-maybe () + "Hide text in minibuffer when `helm-echo-input-in-header-line' is non-nil." + (when (with-helm-buffer helm-echo-input-in-header-line) + (let ((ov (make-overlay (point-min) (point-max) nil nil t))) + (overlay-put ov 'window (selected-window)) + (overlay-put ov 'face (let ((bg-color (face-background 'default nil))) + `(:background ,bg-color :foreground ,bg-color))) + (setq-local cursor-type nil)))) + +(defun evil-collection-helm--set-header-line (&optional update) + "Like `helm--set-header-line' with some Evil-specific tweaks. +- The cursor changes when in Evil insert state. +- Visual selection is highlighted." + (with-selected-window (minibuffer-window) + (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point))) + (end (save-excursion (end-of-visual-line) (point))) + ;; The visual line where the cursor is. + (cont (buffer-substring beg end)) + (pref (propertize + " " + 'display (if (string-match-p (regexp-opt `(,helm--prompt + ,helm--action-prompt)) + cont) + `(space :width ,helm-header-line-space-before-prompt) + (propertize + "->" + 'face 'helm-header-line-left-margin)))) + (pos (- (point) beg))) + ;; Increment pos each time we find a "%" up to current-pos (#1648). + (cl-loop for c across (buffer-substring-no-properties beg (point)) + when (eql c ?%) do (cl-incf pos)) + ;; Increment pos when cursor is on a "%" to make it visible in header-line + ;; i.e "%%|" and not "%|%" (#1649). + (when (eql (char-after) ?%) (setq pos (1+ pos))) + (setq cont (replace-regexp-in-string "%" "%%" cont)) + (let ((state evil-state) + (region-active (region-active-p)) + (m (mark t))) + (with-helm-buffer + (setq header-line-format (concat pref cont " ")) + (when region-active + (setq m (- m beg)) + ;; Increment pos to handle the space before prompt (i.e `pref'). + (put-text-property (1+ (min m pos)) (+ 2 (max m pos)) + 'face + (list :background (face-background 'region)) + header-line-format)) + (put-text-property + ;; Increment pos to handle the space before prompt (i.e `pref'). + (+ 1 pos) (+ 2 pos) + 'face + (if (eq state 'insert) + 'underline + ;; Don't just use 'cursor, this can hide the current character. + (list :inverse-video t + :foreground (face-background 'cursor) + :background (face-background 'default))) + header-line-format) + (when update (force-mode-line-update))))))) + (defun evil-collection-helm-setup () "Set up `evil' bindings for `helm'." + (add-hook 'helm-minibuffer-set-up-hook 'evil-collection-helm-hide-minibuffer-maybe) + (advice-add 'helm--set-header-line :override 'evil-collection-helm--set-header-line) + (evil-define-key '(insert normal) helm-map (kbd "M-[") 'helm-previous-source (kbd "M-]") 'helm-next-source @@ -55,8 +123,8 @@ (dolist (map (list helm-find-files-map helm-read-file-map)) (evil-define-key* 'normal map - "go" 'helm-ff-run-switch-other-window - "/" 'helm-ff-run-find-sh-command) + "go" 'helm-ff-run-switch-other-window + "/" 'helm-ff-run-find-sh-command) (evil-define-key* '(insert normal) map (kbd "S-") 'helm-ff-run-switch-other-window (kbd "M-h") 'helm-find-files-up-one-level)) @@ -83,10 +151,10 @@ (evil-define-key 'normal helm-find-files-map "=" 'helm-ff-run-ediff-file "%" 'helm-ff-run-query-replace-regexp - "D" 'helm-ff-run-delete-file) ; Ivy has "D". + "D" 'helm-ff-run-delete-file) ; Ivy has "D". (evil-define-key 'normal helm-map - (kbd "") 'helm-select-action ; TODO: Ivy has "ga". + (kbd "") 'helm-select-action ; TODO: Ivy has "ga". (kbd "[") 'helm-previous-source (kbd "]") 'helm-next-source "gk" 'helm-previous-source -- cgit v1.0