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.

130 lines
4.7 KiB

4 years ago
  1. ;;; haskell-navigate-imports.el --- A function for cycling through Haskell import lists -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2010 Chris Done
  3. ;; Author: Chris Done <chrisdone@gmail.com>
  4. ;; This file is not part of GNU Emacs.
  5. ;; This program is free software: you can redistribute it and/or
  6. ;; modify it under the terms of the GNU General Public License as
  7. ;; published by the Free Software Foundation, either version 3 of
  8. ;; the License, or (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be
  10. ;; useful, but WITHOUT ANY WARRANTY; without even the implied
  11. ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. ;; PURPOSE. See the GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public
  14. ;; License along with this program. If not, see
  15. ;; <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; The cycling step will stop once at the last import list so
  18. ;; that it is easy to add a new import list.
  19. ;; This module works completely independently of any libraries
  20. ;; (including haskell-mode).
  21. ;; Exports three interactive functions:
  22. ;; 1. haskell-navigate-imports
  23. ;; 2. haskell-navigate-imports-go
  24. ;; 3. haskell-navigate-imports-return
  25. ;; Example usage:
  26. ;; (require 'haskell-navigate-imports)
  27. ;; (define-key haskell-mode-map (kbd "<f8>") 'haskell-navigate-imports)
  28. ;;; Code:
  29. (defvar haskell-navigate-imports-start-point nil)
  30. (defvar haskell-literate) ; defined in haskell-mode.el
  31. ;;;###autoload
  32. (defun haskell-navigate-imports (&optional return)
  33. "Cycle the Haskell import lines or return to point (with prefix arg)."
  34. (interactive "P")
  35. (if return
  36. (haskell-navigate-imports-return)
  37. (haskell-navigate-imports-go)))
  38. ;;;###autoload
  39. (defun haskell-navigate-imports-go ()
  40. "Go to the first line of a list of consecutive import lines. Cycles."
  41. (interactive)
  42. (unless (or (haskell-navigate-imports-line)
  43. (equal (line-beginning-position) (point-min))
  44. (save-excursion (forward-line -1)
  45. (haskell-navigate-imports-line)))
  46. (setq haskell-navigate-imports-start-point (point)))
  47. (haskell-navigate-imports-go-internal))
  48. ;;;###autoload
  49. (defun haskell-navigate-imports-return ()
  50. "Return to the non-import point we were at before going to the module list.
  51. If we were originally at an import list, we can just cycle through easily."
  52. (interactive)
  53. (when haskell-navigate-imports-start-point
  54. (goto-char haskell-navigate-imports-start-point)))
  55. (defun haskell-navigate-imports-go-internal ()
  56. "Go to the first line of a list of consecutive import lines. Cycle."
  57. (if (haskell-navigate-imports-line)
  58. (progn (haskell-navigate-imports-goto-end)
  59. (when (haskell-navigate-imports-find-forward-line)
  60. (haskell-navigate-imports-go-internal)))
  61. (let ((point (haskell-navigate-imports-find-forward-line)))
  62. (if point
  63. (goto-char point)
  64. (progn (goto-char (point-min))
  65. (if (haskell-navigate-imports-find-forward-line)
  66. (haskell-navigate-imports-go-internal)
  67. (let ((module (if (eq haskell-literate 'bird)
  68. "^> ?module"
  69. "^module")))
  70. (when (search-forward-regexp module nil t 1)
  71. (search-forward "\n\n" nil t 1)))))))))
  72. (defun haskell-navigate-imports-goto-end ()
  73. "Skip a bunch of consecutive import lines."
  74. (while (not (or (equal (point)
  75. (point-max))
  76. (not (haskell-navigate-imports-line))))
  77. (forward-line)))
  78. (defun haskell-navigate-imports-find-forward-line ()
  79. "Return a point with at an import line, or nothing."
  80. (save-excursion
  81. (while (not (or (equal (point) (point-max))
  82. (haskell-navigate-imports-after-imports-p) ;; This one just speeds it up.
  83. (haskell-navigate-imports-line)))
  84. (forward-line))
  85. (if (haskell-navigate-imports-line)
  86. (point)
  87. nil)))
  88. (defun haskell-navigate-imports-line ()
  89. "Try to match the current line as a regexp."
  90. (let ((line (buffer-substring-no-properties (line-beginning-position)
  91. (line-end-position)))
  92. (import (if (eq haskell-literate 'bird)
  93. "^> ?import "
  94. "^import ")))
  95. (if (string-match import line)
  96. line
  97. nil)))
  98. (defun haskell-navigate-imports-after-imports-p ()
  99. "Are we after the imports list? Just for a speed boost."
  100. (save-excursion
  101. (goto-char (line-beginning-position))
  102. (not (not (search-forward-regexp "\\( = \\|\\<instance\\>\\| :: \\)"
  103. (line-end-position) t 1)))))
  104. (provide 'haskell-navigate-imports)
  105. ;;; haskell-navigate-imports.el ends here