branch: elpa/zig-mode commit 8f59f86133983975f1d25aefaf7378616c401a1d Author: ventlark <ventl...@gmail.com> Commit: ventlark <ventl...@gmail.com>
Implement beginning/end-of-defun This allows us to use C-M-a and C-M-e to navigate by function blocks. Also includes test, const, and export blocks that contain a brace. --- zig-mode.el | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/zig-mode.el b/zig-mode.el index db9a03b..4e0900b 100644 --- a/zig-mode.el +++ b/zig-mode.el @@ -264,6 +264,67 @@ If given a SOURCE, execute the CMD on it." ;; Skip backwards past whitespace and comment end delimiters. (/= 0 (skip-syntax-backward " >"))))) +(defun zig-in-str-or-cmnt () (nth 8 (syntax-ppss))) +(defconst zig-top-item-beg-re + (concat "^" + (regexp-opt + '("const" "pub" "fn" "extern" "export" "test")) + "[[:space:]]+" + ".*{") + "Start of a Zig item.") + +(defun zig-beginning-of-defun (&optional arg) + "Move backward to the beginning of the current defun. + +With ARG, move backward multiple defuns. Negative ARG means +move forward. + +This is written mainly to be used as `beginning-of-defun-function' for Zig." + (interactive "p") + (let* ((arg (or arg 1)) + (magnitude (abs arg)) + (sign (if (< arg 0) -1 1))) + ;; If moving forward, don't find the defun we might currently be + ;; on. + (when (< sign 0) + (end-of-line)) + (catch 'done + (dotimes (_ magnitude) + ;; Search until we find a match that is not in a string or comment. + (while (if (re-search-backward (concat "^\\(" zig-top-item-beg-re "\\)") + nil 'move sign) + (zig-in-str-or-cmnt) + ;; Did not find it. + (throw 'done nil))))) + t) + (beginning-of-line)) + +(defun zig-end-of-defun () + "Move forward to the next end of defun. + +With argument, do it that many times. +Negative argument -N means move back to Nth preceding end of defun. + +Assume that this is called after `beginning-of-defun'. So point is +at the beginning of the defun body. + +This is written mainly to be used as `end-of-defun-function' for Zig." + (interactive) + ;; Find the opening brace + (if (re-search-forward "[{]" nil t) + (progn + (goto-char (match-beginning 0)) + ;; Go to the closing brace + (condition-case nil + (forward-sexp) + (scan-error + ;; The parentheses are unbalanced; instead of being unable + ;; to fontify, just jump to the end of the buffer + (goto-char (point-max)))) + (end-of-line)) + ;; There is no opening brace, so consider the whole buffer to be one "defun" + (goto-char (point-max)))) + (defun zig-mode-indent-line () (interactive) ;; First, calculate the column that this line should be indented to. @@ -428,6 +489,8 @@ If given a SOURCE, execute the CMD on it." (append zig-electric-indent-chars (and (boundp 'electric-indent-chars) electric-indent-chars))) + (setq-local beginning-of-defun-function 'zig-beginning-of-defun) + (setq-local end-of-defun-function 'zig-end-of-defun) (setq-local indent-line-function 'zig-mode-indent-line) (setq-local indent-tabs-mode nil) ; Zig forbids tab characters. (setq-local syntax-propertize-function 'zig-syntax-propertize)