diff options
author | Austin Clements <aclements@csail.mit.edu> | 2010-01-05 16:50:36 -0800 |
---|---|---|
committer | Austin Clements <aclements@csail.mit.edu> | 2010-01-05 16:50:36 -0800 |
commit | fd28254540b83b885a00da007daffd88b6b0da84 (patch) | |
tree | 89de4aab8d3451a97be8d5a9c86047680698eeb6 | |
parent | 0e7eabf48cdca135bfb6d609d00b9f1ff17a5315 (diff) | |
download | golang-fd28254540b83b885a00da007daffd88b6b0da84.tar.gz |
Update Emacs go-mode for new semicolon rule.
Fixes issue 415.
R=rsc
CC=golang-dev
http://codereview.appspot.com/183104
Committer: Russ Cox <rsc@golang.org>
-rw-r--r-- | misc/emacs/go-mode.el | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el index 88198e3c4..f2dab59eb 100644 --- a/misc/emacs/go-mode.el +++ b/misc/emacs/go-mode.el @@ -59,21 +59,22 @@ st) "Syntax table for Go mode.") +(defvar go-mode-keywords + '("break" "default" "func" "interface" "select" + "case" "defer" "go" "map" "struct" + "chan" "else" "goto" "package" "switch" + "const" "fallthrough" "if" "range" "type" + "continue" "for" "import" "return" "var") + "All keywords in the Go language. Used for font locking and +some syntax analysis.") + (defvar go-mode-font-lock-keywords - (let ((keywords '("import" "package" - "var" "const" "type" "func" - "struct" "interface" - "chan" "map" - "if" "else" "for" "switch" "select" - "range" "case" "default" - "return" "continue" "break" "fallthrough" "goto" - "go" "defer")) - (builtins '("cap" "close" "closed" "len" "make" "new" + (let ((builtins '("cap" "close" "closed" "len" "make" "new" "panic" "panicln" "print" "println")) (constants '("nil" "true" "false" "iota")) (type-name "\\s *\\(?:[*(]\\s *\\)*\\(?:\\w+\\s *\\.\\s *\\)?\\(\\w+\\)") ) - `((,(regexp-opt keywords 'words) . font-lock-keyword-face) + `((,(regexp-opt go-mode-keywords 'words) . font-lock-keyword-face) (,(regexp-opt builtins 'words) . font-lock-builtin-face) (,(regexp-opt constants 'words) . font-lock-constant-face) ;; Function names in declarations @@ -312,6 +313,37 @@ encountered the close character." ;; Indentation ;; +(defvar go-mode-non-terminating-keywords-regexp + (let* ((kws go-mode-keywords) + (kws (remove "break" kws)) + (kws (remove "continue" kws)) + (kws (remove "fallthrough" kws)) + (kws (remove "return" kws))) + (regexp-opt kws 'words)) + "Regular expression matching all Go keywords that *do not* +implicitly terminate a statement.") + +(defun go-mode-semicolon-p () + "True iff point immediately follows either an explicit or +implicit semicolon. Point should immediately follow the last +token on the line." + + ;; #Semicolons + (case (char-before) + ((?\;) t) + ;; String literal + ((?' ?\" ?`) t) + ;; One of the operators and delimiters ++, --, ), ], or } + ((?+) (eq (char-before (1- (point))) ?+)) + ((?-) (eq (char-before (1- (point))) ?-)) + ((?\) ?\] ?\}) t) + ;; An identifier or one of the keywords break, continue, + ;; fallthrough, or return or a numeric literal + (otherwise + (save-excursion + (when (/= (skip-chars-backward "[:word:]_") 0) + (not (looking-at go-mode-non-terminating-keywords-regexp))))))) + (defun go-mode-indentation () "Compute the ideal indentation level of the current line. @@ -335,25 +367,14 @@ indented one level." ;; Inside a multi-line string. Don't mess with indentation. nil) (cs - ;; Inside a multi-line comment + ;; Inside a general comment (goto-char (car cs)) (forward-char 1) (current-column)) - ((not (go-mode-nesting)) - ;; Top-level - (if (or (eolp) - (looking-at "\\<\\(import\\|package\\|const\\|var\\|type\\|func\\)\\>") - (looking-at "//\\|/\\*")) - 0 - ;; Continuation line - ;; XXX If you start typing a new continuation line, nothing - ;; will cause it to be indented. - tab-width)) (t - ;; Neither top-level nor in a multi-line string or comment + ;; Not in a multi-line string or comment (let ((indent 0) - (inside-indenting-paren nil) - (current-line-closes-scope nil)) + (inside-indenting-paren nil)) ;; Count every enclosing brace, plus parens that follow ;; import, const, var, or type and indent according to ;; depth. This simple rule does quite well, but also has a @@ -377,28 +398,21 @@ indented one level." (setq inside-indenting-paren t))))) (setq first nil)))) - (setq current-line-closes-scope - (case (char-after) - ((?\} ?\)) t) - (t nil))) - ;; case, default, and labels are outdented 1 level (when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\(\\S.\\|$\\)") - (decf indent tab-width) - ;; Lines with case, default, etc. also "close" the previous line's - ;; scope, even when there is no semicolon. Don't treat them as - ;; continuation lines. - (setq current-line-closes-scope t)) + (decf indent tab-width)) ;; Continuation lines are indented 1 level (forward-comment (- (buffer-size))) (when (case (char-before) - ((?\{ ?\} ?\; ?:) - ;; Not a continuation line + ((nil ?\{ ?:) + ;; At the beginning of a block or the statement + ;; following a label. nil) ((?\() - ;; Usually a continuation line, unless this paren - ;; counted towards our indentation already + ;; Usually a continuation line in an expression, + ;; unless this paren is part of a factored + ;; declaration. (not inside-indenting-paren)) ((?,) ;; Could be inside a literal. We're a little @@ -411,10 +425,12 @@ indented one level." (and depth (not (eq (char-after (caar depth)) ?\{))))) (t - ;; Except when the current line closes the previous line's - ;; scope, anything else is a continuation line. - (not current-line-closes-scope))) + ;; We're in the middle of a block. Did the + ;; previous line end with an implicit or explicit + ;; semicolon? + (not (go-mode-semicolon-p)))) (incf indent tab-width)) + (max indent 0))))))) (defun go-mode-indent-line () |