diff options
| author | Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | 2019-12-25 15:32:49 -0500 |
|---|---|---|
| committer | Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | 2019-12-25 15:44:42 -0500 |
| commit | cb46614d09a5a0f0ef49efdff9a88bea6372a91a (patch) | |
| tree | f5e915bebda990bc326e5162c58cf18242a29417 /myrddin-mode.el | |
| parent | bcd03d1e7c82911da065422630ec78156ace3773 (diff) | |
Fix issues with indentation.
- Anything at the beginning of a file was screwed up.
- Match arms were screwed up.
Diffstat (limited to 'myrddin-mode.el')
| -rw-r--r-- | myrddin-mode.el | 85 |
1 files changed, 57 insertions, 28 deletions
diff --git a/myrddin-mode.el b/myrddin-mode.el index e7fe7f5..3a2927d 100644 --- a/myrddin-mode.el +++ b/myrddin-mode.el @@ -145,38 +145,67 @@ ;;; Indentation. ;;; +(defun myrddin-mode--preceding-nonempty-line () + "Return the text of and the indentation level of the closest +preceding line that does not consist entirely of whitespace, or +NIL if there is no preceding line." + (unless (bobp) + (save-excursion + (let (last-line) + (while (not (and last-line (plusp (length (string-trim last-line))))) + (previous-line) + (back-to-indentation) + (setf last-line (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) + (values last-line (/ (current-column) myrddin-indent-offset)))))) + + +(defun myrddin-mode--nearest-match-level () + (save-excursion + (while (not (or (bobp) (looking-at "match"))) + (previous-line) + (back-to-indentation)) + (/ (current-column) myrddin-indent-offset))) + +(defun myrddin-mode--calculate-indent (prev-line prev-level) + (save-excursion + (back-to-indentation) + (cond + ;; Handle match arms by finding the indentation of the nearest match + ;; statement. + ((looking-at (rx ?|)) + (* myrddin-indent-offset (myrddin-mode--nearest-match-level))) + ;; Deindent any lines beginning with a syntactic element for closing a + ;; block, unless it occurs immediately following the beginning of a block. + ((looking-at (rx (or "}" ";;" "elif" "else"))) + (if (string-match-p + (rx (eval (cons 'or (cons "{" myrddin-mode-block-keywords)))) + prev-line) + (* myrddin-indent-offset prev-level) + (max 0 (* myrddin-indent-offset (1- prev-level))))) + ;; Indent any lines immediately following a line containing a syntactic + ;; element for opening a block. + ((string-match-p + (rx (eval (cons 'or (append '("|" "{") myrddin-mode-block-keywords)))) + prev-line) + (* myrddin-indent-offset (1+ prev-level))) + (t (* myrddin-indent-offset prev-level))))) + (defun myrddin-mode-indent-line () "Indent current line for Myrddin mode. Return the amount the indentation changed by." (interactive) - (let* ((prev-level (save-excursion - (forward-line -1) - (back-to-indentation) - (/ (current-column) myrddin-indent-offset))) - (prev-line (save-excursion - (forward-line -1) - (back-to-indentation) - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))) - (let ((indent - (save-excursion - (back-to-indentation) - (cond - ((looking-at - (rx (or "}" ";;" "elif" "else"))) - (max 0 (* myrddin-indent-offset (1- prev-level)))) - ((string-match-p - (rx (or "{" "elif" "else" "for" "if" "match" - "struct" "trait" "while")) - prev-line) - (* myrddin-indent-offset (1+ prev-level))) - (t (* myrddin-indent-offset prev-level)))))) - - (if (<= (current-column) (current-indentation)) - (indent-line-to indent) - (save-excursion (indent-line-to indent))) - indent))) + (let ((prev-line (myrddin-mode--preceding-nonempty-line))) + (if prev-line + (cl-destructuring-bind (prev-line prev-level) prev-line + (let ((indent (myrddin-mode--calculate-indent prev-line prev-level))) + (when indent + (if (<= (current-column) (current-indentation)) + (indent-line-to indent) + (save-excursion (indent-line-to indent)))))) + ;; The first line in the file should begin on column 0. + (indent-line-to 0)))) ;;; |