Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 line
5.7 KiB

5 年之前
  1. ;;; ivy-overlay.el --- Overlay display functions for Ivy -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2016-2019 Free Software Foundation, Inc.
  3. ;; Author: Oleh Krehel <ohwoeowho@gmail.com>
  4. ;; Keywords: convenience
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; This package allows to setup Ivy's completion at point to actually
  17. ;; show the candidates and the input at point, instead of in the
  18. ;; minibuffer.
  19. ;;; Code:
  20. (defface ivy-cursor
  21. '((((class color) (background light))
  22. :background "black" :foreground "white")
  23. (((class color) (background dark))
  24. :background "white" :foreground "black"))
  25. "Cursor face for inline completion."
  26. :group 'ivy-faces)
  27. (defvar ivy--old-cursor-type t)
  28. (defvar ivy-overlay-at nil
  29. "Overlay variable for `ivy-display-function-overlay'.")
  30. (declare-function ivy--truncate-string "ivy")
  31. (defun ivy-left-pad (str width)
  32. "Return STR, but with each line indented by WIDTH spaces.
  33. Lines are truncated to the window width."
  34. (let ((padding (make-string width ?\s)))
  35. (mapconcat (lambda (x)
  36. (ivy--truncate-string (concat padding x)
  37. (1- (+ (window-width)
  38. (window-hscroll)))))
  39. (split-string str "\n")
  40. "\n")))
  41. (defun ivy-overlay-cleanup ()
  42. "Clean up after `ivy-display-function-overlay'."
  43. (when (overlayp ivy-overlay-at)
  44. (delete-overlay ivy-overlay-at)
  45. (setq ivy-overlay-at nil))
  46. (unless cursor-type
  47. (setq cursor-type ivy--old-cursor-type))
  48. (when (fboundp 'company-abort)
  49. (company-abort)))
  50. (defvar ivy-height)
  51. (defun ivy-overlay-show-after (str)
  52. "Display STR in an overlay at point.
  53. First, fill each line of STR with spaces to the current column.
  54. Then attach the overlay to the character before point."
  55. (if ivy-overlay-at
  56. (progn
  57. (move-overlay ivy-overlay-at (1- (point)) (line-end-position))
  58. (overlay-put ivy-overlay-at 'invisible nil))
  59. (let ((available-height (count-lines (point) (window-end nil t))))
  60. (unless (>= available-height ivy-height)
  61. (recenter (- (window-height) ivy-height 2))))
  62. (setq ivy-overlay-at (make-overlay (1- (point)) (line-end-position)))
  63. ;; Specify face to avoid clashing with other overlays.
  64. (overlay-put ivy-overlay-at 'face 'default)
  65. (overlay-put ivy-overlay-at 'priority 9999))
  66. (overlay-put ivy-overlay-at 'display str)
  67. (overlay-put ivy-overlay-at 'after-string ""))
  68. (declare-function org-current-level "org")
  69. (declare-function org-at-heading-p "org")
  70. (defvar org-indent-indentation-per-level)
  71. (defvar ivy-height)
  72. (defvar ivy-last)
  73. (defvar ivy-text)
  74. (defvar ivy-completion-beg)
  75. (declare-function ivy-add-face-text-property "ivy")
  76. (declare-function ivy--get-window "ivy")
  77. (declare-function ivy-state-current "ivy")
  78. (declare-function ivy-state-window "ivy")
  79. (declare-function ivy--remove-prefix "ivy")
  80. (defun ivy-overlay-impossible-p (_str)
  81. (or
  82. (and (eq major-mode 'org-mode)
  83. (plist-get (text-properties-at (point)) 'src-block))
  84. (<= (window-height) (+ ivy-height 2))
  85. (= (point) (point-min))
  86. (< (- (+ (window-width) (window-hscroll)) (current-column))
  87. 30)))
  88. (defun ivy-display-function-overlay (str)
  89. "Called from the minibuffer, display STR in an overlay in Ivy window.
  90. Hide the minibuffer contents and cursor."
  91. (if (save-selected-window
  92. (select-window (ivy-state-window ivy-last))
  93. (ivy-overlay-impossible-p str))
  94. (let ((buffer-undo-list t))
  95. (save-excursion
  96. (forward-line 1)
  97. (insert str)))
  98. (ivy-add-face-text-property (minibuffer-prompt-end) (point-max)
  99. '(:foreground "white"))
  100. (setq cursor-type nil)
  101. (with-selected-window (ivy--get-window ivy-last)
  102. (when cursor-type
  103. (setq ivy--old-cursor-type cursor-type))
  104. (setq cursor-type nil)
  105. (let ((overlay-str
  106. (apply
  107. #'concat
  108. (buffer-substring (max (point-min) (1- (point))) (point))
  109. ivy-text
  110. (and (eolp) " ")
  111. (buffer-substring (point) (line-end-position))
  112. (and (> (length str) 0)
  113. (list "\n"
  114. (ivy-left-pad
  115. (ivy--remove-prefix "\n" str)
  116. (+
  117. (if (and (eq major-mode 'org-mode)
  118. (bound-and-true-p org-indent-mode))
  119. (if (org-at-heading-p)
  120. (1- (org-current-level))
  121. (* org-indent-indentation-per-level (org-current-level)))
  122. 0)
  123. (save-excursion
  124. (when ivy-completion-beg
  125. (goto-char ivy-completion-beg))
  126. (current-column)))))))))
  127. (let ((cursor-offset (1+ (length ivy-text))))
  128. (ivy-add-face-text-property cursor-offset (1+ cursor-offset)
  129. 'ivy-cursor overlay-str t))
  130. (ivy-overlay-show-after overlay-str)))))
  131. (provide 'ivy-overlay)
  132. ;;; ivy-overlay.el ends here