emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 5d79ce4: * sm-c-mode: Improve indentation of struct; plus


From: Stefan Monnier
Subject: [elpa] master 5d79ce4: * sm-c-mode: Improve indentation of struct; plus bug fixes
Date: Tue, 24 Nov 2015 21:06:14 +0000

branch: master
commit 5d79ce42f323cd10aed073aac50104a2d7920ec3
Author: Stefan Monnier <address@hidden>
Commit: Stefan Monnier <address@hidden>

    * sm-c-mode: Improve indentation of struct; plus bug fixes
    
    * packages/sm-c-mode/GNUmakefile: New file.
    
    * packages/sm-c-mode/sm-c-mode-test.c: Add some "struct" tests.
    Plus a #include.
    
    * packages/sm-c-mode/sm-c-mode.el (sm-c-syntax-propertize): Mark the <...>
    of #include as a string.
    (sm-c-smie--*-token): Try not to look too far back.
    (sm-c-smie-rules): Indent the {...} of struct and enum definitions.
    (sm-c--bs-realign-1): Fix behavior at EOB.
    (sm-c--cpp-is-not-really-a-comment): New function.
    (comment-only-p): Use it.
---
 packages/sm-c-mode/GNUmakefile      |   21 +++++++++++
 packages/sm-c-mode/sm-c-mode-test.c |   16 ++++++++-
 packages/sm-c-mode/sm-c-mode.el     |   63 ++++++++++++++++++++++++++++------
 3 files changed, 88 insertions(+), 12 deletions(-)

diff --git a/packages/sm-c-mode/GNUmakefile b/packages/sm-c-mode/GNUmakefile
new file mode 100644
index 0000000..2c6da32
--- /dev/null
+++ b/packages/sm-c-mode/GNUmakefile
@@ -0,0 +1,21 @@
+
+EMACS=emacs
+DIFF=diff
+
+test: sm-c-mode-test.c.test
+
+.PHONY: refresh
+refresh:
+
+%.elc : %.el
+       $(EMACS) --batch -L . --no-init-file -f batch-byte-compile $<
+
+%.test: % sm-c-mode.elc refresh
+       $(EMACS) --batch -l sm-c-mode-autoloads.el               \
+           sm-c-mode-test.c                                     \
+           --eval '(setq indent-tabs-mode nil)'                 \
+           --eval '(setq create-lockfiles nil)'                 \
+           --eval '(indent-region (point-min) (point-max) nil)' \
+           --eval '(indent-region (point-min) (point-max) nil)' \
+           --eval '(write-region (point-min) (point-max) "$@")'
+       $(DIFF) $< $@ || true; $(RM) $@
diff --git a/packages/sm-c-mode/sm-c-mode-test.c 
b/packages/sm-c-mode/sm-c-mode-test.c
index 94cf476..4690105 100644
--- a/packages/sm-c-mode/sm-c-mode-test.c
+++ b/packages/sm-c-mode/sm-c-mode-test.c
@@ -1,5 +1,7 @@
 /* -*- sm-c -*- */
 
+#include <toto>
+
 #define toto(arg) /* bla
                      bla */ \
   if (a) {  /* toto
@@ -11,7 +13,19 @@
 #define test(arg) \
   (hello + arg)
 
-struct foo;
+struct foo
+  {
+    int field;
+  };
+
+struct foo {
+  int field;
+};
+
+struct foo *getfoo (void)
+{
+  return NULL;
+}
 
 #define titi(arg) { \
     if (a) {        \
diff --git a/packages/sm-c-mode/sm-c-mode.el b/packages/sm-c-mode/sm-c-mode.el
index 7616616..1ac263e 100644
--- a/packages/sm-c-mode/sm-c-mode.el
+++ b/packages/sm-c-mode/sm-c-mode.el
@@ -35,9 +35,8 @@
 ;; it'd be nice to hook the sm-c--while-to-do, sm-c--else-to-if, and sm-c--boi
 ;; functions into SMIE at some level.
 
-;; FIXME:
-;; - M-; mistakes # for a comment in CPP directives!
-;; Ha!  As if this was the only/main problem!
+;; Note that this mode makes no attempt to try and handle sanely K&R style
+;; function definitions.
 
 ;;; Code:
 
@@ -233,7 +232,15 @@ Typically 2 for GNU style and `tab-width' for Linux style."
   (sm-c--cpp-syntax-propertize end)
   (funcall
    (syntax-propertize-rules
-    (sm-c--cpp-regexp (2 (prog1 "< c" (sm-c--cpp-syntax-propertize end)))))
+    (sm-c--cpp-regexp
+     (2 (prog1 "< c"
+          (when (and (equal (match-string 3) "include")
+                     (looking-at "[ \t]*\\(<\\)[^>\n]*\\(>\\)"))
+            (put-text-property (match-beginning 1) (match-end 1)
+                               'syntax-table (string-to-syntax "|"))
+            (put-text-property (match-beginning 2) (match-end 2)
+                               'syntax-table (string-to-syntax "|")))
+          (sm-c--cpp-syntax-propertize end)))))
    (point) end))
 
 (defun sm-c-syntactic-face-function (ppss)
@@ -495,9 +502,19 @@ if INNER is non-nil, it stops at the innermost one."
         ((or "(" "[" "{" "}") "* deref")
         (`nil
          (goto-char pos)
-         (pcase (smie-backward-sexp "* mult")
-           (`(,_ ,_ ,(or ";" "{")) "* deref")
-           (_ "* mult")))
+         (let ((res nil))
+           (while (not res)
+             (pcase (smie-backward-sexp)
+               (`(,_ ,_ ,(or ";" "{")) (setq res "* deref"))
+               ((and `nil (guard (looking-at "{"))) (setq res "* deref"))
+               (`(,left ,_ ,op)
+                (if (and (numberp left)
+                         (numberp (nth 2 (assoc op smie-grammar)))
+                         (< (nth 2 (assoc op smie-grammar))
+                            (nth 1 (assoc "* mult" smie-grammar))))
+                    (smie-backward-sexp 'halfsexp)
+                  (setq res "* mult")))))
+           res))
         (_ "* mult")))))
 
 (defun sm-c-smie-hanging-eolp ()
@@ -565,8 +582,20 @@ if INNER is non-nil, it stops at the innermost one."
            (sm-c--boi 'inner) (sm-c--skip-labels (point-max))
            (let ((tok (save-excursion (sm-c-smie-forward-token))))
              (cond
-              ((member tok '("typedef")) ; "enum" "struct"
-               `(column . ,(+ (funcall smie-rules-function :elem 'basic)
+              ((or (equal tok "typedef")
+                   (and (member tok '("enum" "struct"))
+                        ;; Make sure that the {...} is about this struct/enum,
+                        ;; as opposed to "struct foo *get_foo () {...}"!
+                        (save-excursion
+                          (smie-indent-forward-token)
+                          (smie-indent-forward-token)
+                          (forward-comment (point-max))
+                          (>= (point) pos))))
+               `(column . ,(+ (if (save-excursion
+                                    (goto-char pos)
+                                    (smie-rule-hanging-p))
+                                  0
+                                (funcall smie-rules-function :elem 'basic))
                               (smie-indent-virtual))))
               ((or (member tok sm-c-paren-block-keywords)
                    (equal tok "do"))
@@ -689,6 +718,7 @@ if INNER is non-nil, it stops at the innermost one."
     (end-of-line)
     (unless (zerop (mod (skip-chars-backward "\\\\") 2))
       (skip-chars-backward " \t")
+      (setq from (point))
       (let ((col (current-column))
             start end)
         (while
@@ -702,14 +732,14 @@ if INNER is non-nil, it stops at the innermost one."
         (while
             (progn (setq end (point))
                    (end-of-line 2)
-                   (and (> (point) start)
+                   (and (> (line-beginning-position) end)
                         (not (zerop (mod (skip-chars-backward "\\\\") 2)))))
           (skip-chars-backward " \t")
           (setq col (max (current-column) col)))
         (goto-char to)
         (beginning-of-line)
         (unless (or (> (point) end)       ;Don't realign if we changed outside!
-                    (< end start))        ;A lone \
+                    (<= end start))        ;A lone \
           
           (setq col (1+ col))         ;Add a space before the backslashes.
           (goto-char end)
@@ -801,5 +831,16 @@ if INNER is non-nil, it stops at the innermost one."
   (add-hook 'after-change-functions #'sm-c--bs-after-change nil t)
   (add-hook 'post-command-hook #'sm-c--bs-realign nil t))
 
+(defun sm-c--cpp-is-not-really-a-comment (&rest args)
+  ;; Without this, placing the region around a CPP directive and hitting
+  ;; M-; would just strip the leading "#" instead of commenting things out.
+  (if (not (derived-mode-p 'sm-c-mode))
+      (apply args)
+    (let ((parse-sexp-lookup-properties nil))
+      (apply args))))
+
+;; FIXME: Clearly, we should change newcomment.el instead.
+(advice-add 'comment-only-p :around #'sm-c--cpp-is-not-really-a-comment)
+
 (provide 'sm-c-mode)
 ;;; sm-c-mode.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]