From b6d68e3276c8e4417d4635d6df64727dab1a4805 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Wed, 6 Nov 2024 00:22:54 +0300 Subject: [PATCH] Implement going to the beginning of a defun MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements support for `(beginning-of-defun)`. As a side note, the match is done inside a single line string because I tried implementing a regexp to make Emacs to restrain to a single line, and it turned out to be very hard. I didn't succeed at that for like ½-hour I spent, and constraining the search artifically turned out not just much easier, but also significantly simplified the regexp. --- purescript-mode.el | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/purescript-mode.el b/purescript-mode.el index 205c67e..56a7255 100644 --- a/purescript-mode.el +++ b/purescript-mode.el @@ -340,6 +340,7 @@ see documentation for that variable for more details." (set (make-local-variable 'dabbrev-case-distinction) nil) (set (make-local-variable 'dabbrev-case-replace) nil) (set (make-local-variable 'dabbrev-abbrev-char-regexp) "\\sw\\|[.]") + (setq-local beginning-of-defun-function 'purescript-beginning-of-defun) (setq prettify-symbols-alist purescript-font-lock-prettify-symbols-alist) (when (bound-and-true-p purescript-font-lock-symbols) (warn "`purescript-font-lock-symbols' is obsolete: please enable `prettify-symbols-mode' locally or globally instead.")) @@ -470,6 +471,35 @@ Brings up the documentation for purescript-mode-hook." (format " [ %s .. ]" (purescript-string-take (purescript-trim (cadr lines)) 10)) "")))))) +(defun purescript-current-line-string () + "Returns current line as a string." + (buffer-substring-no-properties (line-beginning-position) (line-end-position))) + +(defun purescript-beginning-of-defun-single () + (while (and (looking-at-p (rx (* space) eol)) + (not (bobp))) + (forward-line -1)) ; can't get indentation on an empty line + (let ((indent-level (current-indentation))) + (while + (not + (or (ignore (forward-line -1)) ; do-while implementation + (bobp) + (and (< (current-indentation) indent-level) + (string-match-p + (rx (*? anything) + (or bol space word-boundary) "=" + (or eol space word-boundary)) + ;; Emacs doesn't allow to limit search just to the curent line + ;; barring the regex eol, but eol overly complicates matching. + (purescript-current-line-string)))))))) + +(defun purescript-beginning-of-defun (&optional repeat) + "Move point to the beginning of the current PureScript function." + (purescript-beginning-of-defun-single) + (dotimes (_ (if repeat + (- repeat 1) ; the function was already called once + 0)) + (purescript-beginning-of-defun-single))) (provide 'purescript-mode)