al-ivy.el 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. ;;; al-ivy.el-- Additional functionality for ivy-mode
  2. ;; Copyright © 2017 Alex Kost
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;;
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Code:
  16. (require 'ivy)
  17. (require 'al-imenu)
  18. (defvar al/ivy-flx-enabled? (require 'flx nil t))
  19. (defun al/ivy-imenu-sort (name candidates)
  20. "Re-sort CANDIDATES, an `imenu' index that contains NAME.
  21. Put `al/imenu-eval-after-load-group' and
  22. `al/imenu-sections-group' groups in the beginning."
  23. ;; The code originates from `ivy-sort-function-buffer'.
  24. (if (< (length name) 2)
  25. candidates
  26. (let* ((candidates (if al/ivy-flx-enabled?
  27. (ivy--flx-sort name candidates)
  28. candidates))
  29. (after-load-re (rx-to-string
  30. `(and string-start
  31. ,al/imenu-eval-after-load-group)
  32. t))
  33. (section-re (rx-to-string
  34. `(and string-start
  35. ,al/imenu-sections-group)
  36. t))
  37. after-load-res
  38. section-res
  39. rest)
  40. (dolist (s candidates)
  41. (cond
  42. ((string-match-p after-load-re s)
  43. (push s after-load-res))
  44. ((string-match-p section-re s)
  45. (push s section-res))
  46. (t
  47. (push s rest))))
  48. (nconc
  49. (nreverse after-load-res)
  50. (nreverse section-res)
  51. (nreverse rest)))))
  52. (defun al/ivy-add-prompt-count (prompt)
  53. "Substitution for `ivy-add-prompt-count'.
  54. The problem with that `ivy-add-prompt-count' is that it doesn't
  55. respect \"%\" character, i.e. when PROMPT contains \"%\", it will
  56. not be replaced with \"%%\", and later `ivy--insert-prompt' will
  57. fail trying to `format' a string with unexpected \"%\" signs."
  58. (if (string-match-p "%.*d" ivy-count-format)
  59. (concat ivy-count-format
  60. (if (string-match "%" prompt)
  61. (replace-match "%%" t nil prompt)
  62. prompt))
  63. prompt))
  64. (defvar al/ivy-format-selected "─► ")
  65. (defvar al/ivy-format-other " ")
  66. (defun al/ivy-format-function (candidates)
  67. "Transform CANDIDATES into a string for minibuffer.
  68. This function is suitable for `ivy-format-function'."
  69. (ivy--format-function-generic
  70. (lambda (str)
  71. (concat al/ivy-format-selected
  72. (propertize str 'face 'ivy-current-match)))
  73. (lambda (str)
  74. (concat al/ivy-format-other str))
  75. candidates
  76. "\n"))
  77. ;;;###autoload
  78. (defun al/ivy-partial ()
  79. "Complete the current candidate."
  80. (interactive)
  81. ;; Remove potential trailing slash.
  82. (let ((new (if (string-match "\\(.*\\)/\\'" (ivy-state-current ivy-last))
  83. (match-string 1 (ivy-state-current ivy-last))
  84. (ivy-state-current ivy-last))))
  85. (delete-region (minibuffer-prompt-end) (point-max))
  86. (insert new)))
  87. ;;;###autoload
  88. (defun al/ivy-copy-current-item ()
  89. "Put the current ivy item into `kill-ring'."
  90. (interactive)
  91. (kill-new (ivy-state-current ivy-last)))
  92. (declare-function magit-status "magit" t)
  93. ;;;###autoload
  94. (defun al/ivy-magit-status ()
  95. "Run `magit-status' from the current ivy find file prompt.
  96. It uses the currently specified directory or the current
  97. completion directory if there is some input."
  98. (interactive)
  99. (ivy-exit-with-action
  100. (lambda (_)
  101. (let ((default-directory
  102. (if (string= "" ivy-text)
  103. ivy--directory
  104. (expand-file-name (ivy-state-current ivy-last)
  105. ivy--directory))))
  106. (magit-status)))))
  107. (provide 'al-ivy)
  108. ;;; al-ivy.el ends here