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.

131 lines
4.8 KiB

4 years ago
  1. ;;; haskell-complete-module.el --- A fast way to complete Haskell module names -*- lexical-binding: t -*-
  2. ;; Copyright (c) 2014 Chris Done. All rights reserved.
  3. ;; This file 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, or (at your option)
  6. ;; any later version.
  7. ;; This file is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;;; Code:
  14. (require 'cl-lib)
  15. (defcustom haskell-complete-module-preferred
  16. '()
  17. "Override ordering of module results by specifying preferred modules."
  18. :group 'haskell
  19. :type '(repeat string))
  20. (defcustom haskell-complete-module-max-display
  21. 10
  22. "Maximum items to display in minibuffer."
  23. :group 'haskell
  24. :type 'number)
  25. (defun haskell-complete-module-read (prompt candidates)
  26. "Interactively auto-complete from a list of candidates."
  27. (let ((stack (list))
  28. (pattern "")
  29. (result nil))
  30. (delete-dups candidates)
  31. (setq candidates
  32. (sort candidates
  33. (lambda (a b)
  34. (let ((a-mem (member a haskell-complete-module-preferred))
  35. (b-mem (member b haskell-complete-module-preferred)))
  36. (cond
  37. ((and a-mem (not b-mem))
  38. t)
  39. ((and b-mem (not a-mem))
  40. nil)
  41. (t
  42. (string< a b)))))))
  43. (while (not result)
  44. (let ((key
  45. (key-description
  46. (vector
  47. (read-key
  48. (concat (propertize prompt 'face 'minibuffer-prompt)
  49. (propertize pattern 'face 'font-lock-type-face)
  50. "{"
  51. (mapconcat #'identity
  52. (let* ((i 0))
  53. (cl-loop for candidate in candidates
  54. while (<= i haskell-complete-module-max-display)
  55. do (cl-incf i)
  56. collect (cond ((> i haskell-complete-module-max-display)
  57. "...")
  58. ((= i 1)
  59. (propertize candidate 'face 'ido-first-match-face))
  60. (t candidate))))
  61. " | ")
  62. "}"))))))
  63. (cond
  64. ((string= key "C-g")
  65. (keyboard-quit))
  66. ((string= key "DEL")
  67. (unless (null stack)
  68. (setq candidates (pop stack)))
  69. (unless (string= "" pattern)
  70. (setq pattern (substring pattern 0 -1))))
  71. ((string= key "RET")
  72. (setq result (or (car candidates)
  73. pattern)))
  74. ((string= key "<left>")
  75. (setq candidates
  76. (append (last candidates)
  77. (butlast candidates))))
  78. ((string= key "<right>")
  79. (setq candidates
  80. (append (cdr candidates)
  81. (list (car candidates)))))
  82. (t
  83. (when (string-match "[A-Za-z0-9_'.]+" key)
  84. (push candidates stack)
  85. (setq pattern (concat pattern key))
  86. (setq candidates (haskell-complete-module pattern candidates)))))))
  87. result))
  88. (defun haskell-complete-module (pattern candidates)
  89. "Filter the CANDIDATES using PATTERN."
  90. (let ((case-fold-search t))
  91. (cl-loop for candidate in candidates
  92. when (haskell-complete-module-match pattern candidate)
  93. collect candidate)))
  94. (defun haskell-complete-module-match (pattern text)
  95. "Match PATTERN against TEXT."
  96. (string-match (haskell-complete-module-regexp pattern)
  97. text))
  98. (defun haskell-complete-module-regexp (pattern)
  99. "Make a regular expression for the given module pattern. Example:
  100. \"c.m.s\" -> \"^c[^.]*\\.m[^.]*\\.s[^.]*\"
  101. "
  102. (let ((components (mapcar #'haskell-complete-module-component
  103. (split-string pattern "\\." t))))
  104. (concat "^"
  105. (mapconcat #'identity
  106. components
  107. "\\."))))
  108. (defun haskell-complete-module-component (component)
  109. "Make a regular expression for the given component. Example:
  110. \"co\" -> \"c[^.]*o[^.]*\"
  111. "
  112. (replace-regexp-in-string "\\(.\\)" "\\1[^.]*" component))
  113. (provide 'haskell-complete-module)