aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <aclements@csail.mit.edu>2010-01-05 16:50:36 -0800
committerRuss Cox <rsc@golang.org>2010-01-05 16:50:36 -0800
commit6712cf365b68d492e1f62b70922e198f4cb9fad8 (patch)
treed1f38ebe707192f9adfdfcc9eb06c66172d7c891
parentcfbee34a277d75c19b843c27ef053b78c493b32d (diff)
downloadgo-6712cf365b68d492e1f62b70922e198f4cb9fad8.tar.gz
go-6712cf365b68d492e1f62b70922e198f4cb9fad8.zip
Update Emacs go-mode for new semicolon rule.
Fixes #415. R=rsc CC=golang-dev https://golang.org/cl/183104
-rw-r--r--misc/emacs/go-mode.el98
1 files changed, 57 insertions, 41 deletions
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 88198e3c4d..f2dab59eb8 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 ()