[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 8ab7041 297/433: Adjust indentation in primary mode for ER
From: |
Dmitry Gutov |
Subject: |
[elpa] master 8ab7041 297/433: Adjust indentation in primary mode for ERB blocks |
Date: |
Thu, 15 Mar 2018 19:44:23 -0400 (EDT) |
branch: master
commit 8ab704156fd3808a7061a2e2cbb3190c4612333f
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>
Adjust indentation in primary mode for ERB blocks
---
mmm-erb.el | 157 +++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 110 insertions(+), 47 deletions(-)
diff --git a/mmm-erb.el b/mmm-erb.el
index 53f472e..1e51507 100644
--- a/mmm-erb.el
+++ b/mmm-erb.el
@@ -46,14 +46,14 @@
(pushnew '(indent-line-function buffer) mmm-save-local-variables)
-(dolist (mode (list 'html-erb-mode 'nxml-mode))
- (mmm-add-mode-ext-class mode "\\.html\\(\\.erb\\)?\\'" 'html-js)
- (mmm-add-mode-ext-class mode "\\.html\\(\\.erb\\)?\\'" 'html-css)
- (mmm-add-mode-ext-class mode "\\.html\\.erb\\'" 'erb)
- (mmm-add-mode-ext-class mode "\\.jst\\.ejs\\'" 'ejs))
+(mmm-add-mode-ext-class 'html-erb-mode "\\.html\\(\\.erb\\)?\\'" 'html-js)
+(mmm-add-mode-ext-class 'html-erb-mode "\\.html\\(\\.erb\\)?\\'" 'html-css)
+(mmm-add-mode-ext-class 'html-erb-mode "\\.html\\.erb\\'" 'erb)
+(mmm-add-mode-ext-class 'html-erb-mode "\\.jst\\.ejs\\'" 'ejs)
;;;###autoload
(define-derived-mode html-erb-mode html-mode "ERB-HTML"
+ (setq sgml-unclosed-tags nil) ; Simplifies indentation logic.
(add-hook 'mmm-html-erb-mode-hook 'mmm-erb-process-submode nil t)
(add-hook 'mmm-ruby-mode-submode-hook 'mmm-erb-process-submode nil t)
(add-hook 'mmm-css-mode-submode-hook 'mmm-erb-process-submode nil t)
@@ -65,49 +65,39 @@
(defun mmm-erb-indent-line ()
(interactive)
(mmm-update-submode-region)
- (destructuring-bind (primary-indent-function submode-indent-function)
- (mapcar (lambda (mode) (cadr (assoc 'indent-line-function
- (get mode 'mmm-local-variables))))
- (list mmm-primary-mode mmm-current-submode))
- (let (added-whitespace)
- (if (and mmm-current-overlay mmm-current-submode
- ;; Region starts before the current line.
- (< (overlay-start mmm-current-overlay)
- (point-at-bol)))
- (if (<= (overlay-end mmm-current-overlay)
- (save-excursion (back-to-indentation) (point)))
- ;; We're at a closing tag.
- (mmm-erb-indent-to-region-start)
- (save-restriction
- (save-excursion
- (goto-char (overlay-start mmm-current-overlay))
- (when (not (looking-at "^\\|\\s-*$"))
- ;; Submode region has text on the same line as the opening
tag,
- ;; pad it with whitespace to make the following lines line
up.
- (setq added-whitespace (current-column))
- (insert-char ?\s added-whitespace)))
- (narrow-to-region (overlay-start mmm-current-overlay)
- (overlay-end mmm-current-overlay))
- (funcall submode-indent-function)
- (when added-whitespace
- ;; Remove the padding.
- (save-excursion
- (goto-char (overlay-start mmm-current-overlay))
- (delete-char added-whitespace))))
- ;; If submode indent function moved us to bol,
- ;; we're on the top level, indent according to the primary mode.
- (when (zerop (current-indentation))
- (mmm-erb-indent-to-region-start
- (mmm-erb-indent-offset mmm-primary-mode))))
- (funcall primary-indent-function)))))
+ (if (and mmm-current-overlay mmm-current-submode
+ (< (overlay-start mmm-current-overlay) (point-at-bol)))
+ ;; Region starts before the current line (hence, contains indentation).
+ (mmm-erb-indent-line-submode)
+ (mmm-erb-indent-line-primary)))
-(defvar mmm-erb-offset-var-alist
- '((html-erb-mode . sgml-basic-offset)
- (nxml-mode . nxml-child-indent)))
-
-(defun mmm-erb-indent-offset (mode)
- (let ((name (cdr (assoc mode mmm-erb-offset-var-alist))))
- (when name (symbol-value name))))
+(defun mmm-erb-indent-line-submode ()
+ (let (added-whitespace)
+ (if (<= (overlay-end mmm-current-overlay)
+ (save-excursion (back-to-indentation) (point)))
+ ;; We're at a closing tag.
+ (mmm-erb-indent-to-region-start)
+ (save-restriction
+ (save-excursion
+ (goto-char (overlay-start mmm-current-overlay))
+ (when (not (looking-at "^\\|\\s-*$"))
+ ;; Submode region has text on the same line as the opening tag,
+ ;; pad it with whitespace to make the following lines line up.
+ (setq added-whitespace (current-column))
+ (insert-char ?\s added-whitespace)))
+ (narrow-to-region (overlay-start mmm-current-overlay)
+ (overlay-end mmm-current-overlay))
+ (funcall (mmm-erb-orig-indent-function mmm-current-submode))
+ (when added-whitespace
+ ;; Remove the padding.
+ (save-excursion
+ (goto-char (overlay-start mmm-current-overlay))
+ (delete-char added-whitespace))))
+ ;; If submode indent function moved us to bol,
+ ;; we're on the top level, indent according to the primary mode.
+ (when (zerop (current-indentation))
+ (mmm-erb-indent-to-region-start
+ (mmm-erb-indent-offset mmm-primary-mode))))))
(defun mmm-erb-indent-to-region-start (&optional additional-offset)
(let* ((indent (current-indentation))
@@ -119,4 +109,77 @@
(or additional-offset 0))))
(when (> offset 0) (forward-char offset))))
+(defun mmm-erb-indent-line-primary ()
+ (save-excursion
+ (let* ((here (point))
+ ;; Before previous line's tag.
+ (start (progn (forward-line -1)
+ (back-to-indentation)
+ (let ((lcon (sgml-lexical-context)))
+ (when (eq (car lcon) 'tag)
+ ;; Tag spreads several lines.
+ (goto-char (cdr lcon))
+ (back-to-indentation)))
+ (point)))
+ (regions (mmm-regions-in start here))
+ (offset (- (current-column) (current-indentation)))
+ (n 0))
+ ;; Collect indent modifier depending on type of tags.
+ (loop for region in regions
+ for type = (mmm-erb-scan-region region)
+ when type do
+ (if (eq type 'close)
+ (when (plusp n) (decf n))
+ (incf n (if (eq type 'close) 0 1))))
+ (let ((eol (progn (goto-char here) (end-of-line 1) (point))))
+ ;; There can be primary mode regions in the list, so we loop.
+ ;; Look for "else" and "end" instructions.
+ ;; If a block start instruction comes first, don't adjust modifier.
+ (loop for region in (mmm-regions-in here eol)
+ for type = (mmm-erb-scan-region region)
+ until (eq type 'open)
+ when (memq type '(middle close)) do (decf n)))
+ (goto-char here)
+ (funcall (mmm-erb-orig-indent-function mmm-primary-mode))
+ (let* ((indent (current-indentation))
+ (indent-step (mmm-erb-indent-offset mmm-primary-mode)))
+ (indent-line-to (+ indent (if n (* indent-step n) 0)))
+ (when (> offset 0) (forward-char offset))))))
+
+(defun mmm-erb-scan-region (region)
+ (when region ; Can be nil if a line is empty, for example.
+ (destructuring-bind (submode beg end) region
+ (let ((scan-fn (plist-get '(ruby-mode mmm-erb-scan-erb
+ js-mode mmm-erb-scan-ejs)
+ submode)))
+ (when scan-fn
+ (save-excursion
+ (goto-char beg)
+ (skip-syntax-forward "-")
+ (funcall scan-fn end)))))))
+
+(defun mmm-erb-scan-erb (limit)
+ (cond ((looking-at "\\(?:if\\|unless\\|for\\|while\\)\\b") 'open)
+ ((looking-at "\\(?:else\\|elsif\\)\\b") 'middle)
+ ((looking-at "end\\b\\|}") 'close)
+ ((re-search-forward (concat "\\(?: +do +\\| *{ *\\)"
+ "\\(?:|[A-Za-z0-9_, ]*|\\)? *") limit t)
+ 'open)))
+
+(defun mmm-erb-scan-ejs (limit)
+ (cond ((looking-at "\\(?:if\\|for\\|while\\)\\b") 'open)
+ ((looking-at "} *else\\b") 'middle)
+ ((looking-at "}") 'close)))
+
+(defun mmm-erb-orig-indent-function (mode)
+ (cadr (assoc 'indent-line-function (get mode 'mmm-local-variables))))
+
+(defvar mmm-erb-offset-var-alist
+ '((html-erb-mode . sgml-basic-offset)
+ (nxml-mode . nxml-child-indent)))
+
+(defun mmm-erb-indent-offset (mode)
+ (let ((name (cdr (assoc mode mmm-erb-offset-var-alist))))
+ (when name (symbol-value name))))
+
(provide 'mmm-erb)
- [elpa] master 9674355 328/433: Merge pull request #18 from prakashk/master, (continued)
- [elpa] master 9674355 328/433: Merge pull request #18 from prakashk/master, Dmitry Gutov, 2018/03/15
- [elpa] master 05a787e 291/433: Fix further compilation warnings in recent Emacsen, Dmitry Gutov, 2018/03/15
- [elpa] master e269a47 305/433: Require 'mmm-region from 'mmm-erb, avoiding compilation warnings about free variable references, Dmitry Gutov, 2018/03/15
- [elpa] master 961a127 263/433: Prevent bounds from going outside buffer (XEmacs complains), Dmitry Gutov, 2018/03/15
- [elpa] master 66b47cd 218/433: Released 0.4.7, Dmitry Gutov, 2018/03/15
- [elpa] master 07b35d4 250/433: Added mmm-noweb to autoload (Joe Kelsey), Dmitry Gutov, 2018/03/15
- [elpa] master b554efb 287/433: After fontifying the region, restore local vars, Dmitry Gutov, 2018/03/15
- [elpa] master 0922481 254/433: Added narrow to submode region (Joe Kelsey), Dmitry Gutov, 2018/03/15
- [elpa] master b72e44c 369/433: Released 0.5.1, Dmitry Gutov, 2018/03/15
- [elpa] master bcc5adf 351/433: Define mmm-indent-line-function and its default value, Dmitry Gutov, 2018/03/15
- [elpa] master 8ab7041 297/433: Adjust indentation in primary mode for ERB blocks,
Dmitry Gutov <=
- [elpa] master 68b2135 282/433: Fix obsolete backquotes, Dmitry Gutov, 2018/03/15
- [elpa] master e3ef1f8 267/433: Collapsed undo of insertion into one command., Dmitry Gutov, 2018/03/15
- [elpa] master 6dcd817 337/433: * mmm-syntax-propertize-function: Use font-lock-syntactic-keywords, Dmitry Gutov, 2018/03/15
- [elpa] master ea8a1b8 342/433: Rebinding syntax-propertize-chunk-size is pointless, Dmitry Gutov, 2018/03/15
- [elpa] master 970b52a 298/433: Check for EJS "blocks", Dmitry Gutov, 2018/03/15
- [elpa] master 20e65af 372/433: Primary mode spf should see the whole buffer, Dmitry Gutov, 2018/03/15
- [elpa] master 2590b31 401/433: Update the checklist, Dmitry Gutov, 2018/03/15
- [elpa] master 5f80383 364/433: Fix typo: global-mmm-mode -> mmm-global-mode, Dmitry Gutov, 2018/03/15
- [elpa] master 7422b45 341/433: * mmm-regions-in: Keep overlay references in the return value, Dmitry Gutov, 2018/03/15
- [elpa] master 6156c7a 349/433: Add URL header, Dmitry Gutov, 2018/03/15