Commit 6712cf36 authored by Austin Clements's avatar Austin Clements Committed by Russ Cox

Update Emacs go-mode for new semicolon rule.

Fixes #415.

R=rsc
CC=golang-dev
https://golang.org/cl/183104
parent cfbee34a
...@@ -59,21 +59,22 @@ ...@@ -59,21 +59,22 @@
st) st)
"Syntax table for Go mode.") "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 (defvar go-mode-font-lock-keywords
(let ((keywords '("import" "package" (let ((builtins '("cap" "close" "closed" "len" "make" "new"
"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"
"panic" "panicln" "print" "println")) "panic" "panicln" "print" "println"))
(constants '("nil" "true" "false" "iota")) (constants '("nil" "true" "false" "iota"))
(type-name "\\s *\\(?:[*(]\\s *\\)*\\(?:\\w+\\s *\\.\\s *\\)?\\(\\w+\\)") (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 builtins 'words) . font-lock-builtin-face)
(,(regexp-opt constants 'words) . font-lock-constant-face) (,(regexp-opt constants 'words) . font-lock-constant-face)
;; Function names in declarations ;; Function names in declarations
...@@ -312,6 +313,37 @@ encountered the close character." ...@@ -312,6 +313,37 @@ encountered the close character."
;; Indentation ;; 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 () (defun go-mode-indentation ()
"Compute the ideal indentation level of the current line. "Compute the ideal indentation level of the current line.
...@@ -335,25 +367,14 @@ indented one level." ...@@ -335,25 +367,14 @@ indented one level."
;; Inside a multi-line string. Don't mess with indentation. ;; Inside a multi-line string. Don't mess with indentation.
nil) nil)
(cs (cs
;; Inside a multi-line comment ;; Inside a general comment
(goto-char (car cs)) (goto-char (car cs))
(forward-char 1) (forward-char 1)
(current-column)) (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 (t
;; Neither top-level nor in a multi-line string or comment ;; Not in a multi-line string or comment
(let ((indent 0) (let ((indent 0)
(inside-indenting-paren nil) (inside-indenting-paren nil))
(current-line-closes-scope nil))
;; Count every enclosing brace, plus parens that follow ;; Count every enclosing brace, plus parens that follow
;; import, const, var, or type and indent according to ;; import, const, var, or type and indent according to
;; depth. This simple rule does quite well, but also has a ;; depth. This simple rule does quite well, but also has a
...@@ -377,28 +398,21 @@ indented one level." ...@@ -377,28 +398,21 @@ indented one level."
(setq inside-indenting-paren t))))) (setq inside-indenting-paren t)))))
(setq first nil)))) (setq first nil))))
(setq current-line-closes-scope
(case (char-after)
((?\} ?\)) t)
(t nil)))
;; case, default, and labels are outdented 1 level ;; case, default, and labels are outdented 1 level
(when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\(\\S.\\|$\\)") (when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\(\\S.\\|$\\)")
(decf indent tab-width) (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))
;; Continuation lines are indented 1 level ;; Continuation lines are indented 1 level
(forward-comment (- (buffer-size))) (forward-comment (- (buffer-size)))
(when (case (char-before) (when (case (char-before)
((?\{ ?\} ?\; ?:) ((nil ?\{ ?:)
;; Not a continuation line ;; At the beginning of a block or the statement
;; following a label.
nil) nil)
((?\() ((?\()
;; Usually a continuation line, unless this paren ;; Usually a continuation line in an expression,
;; counted towards our indentation already ;; unless this paren is part of a factored
;; declaration.
(not inside-indenting-paren)) (not inside-indenting-paren))
((?,) ((?,)
;; Could be inside a literal. We're a little ;; Could be inside a literal. We're a little
...@@ -411,10 +425,12 @@ indented one level." ...@@ -411,10 +425,12 @@ indented one level."
(and depth (and depth
(not (eq (char-after (caar depth)) ?\{))))) (not (eq (char-after (caar depth)) ?\{)))))
(t (t
;; Except when the current line closes the previous line's ;; We're in the middle of a block. Did the
;; scope, anything else is a continuation line. ;; previous line end with an implicit or explicit
(not current-line-closes-scope))) ;; semicolon?
(not (go-mode-semicolon-p))))
(incf indent tab-width)) (incf indent tab-width))
(max indent 0))))))) (max indent 0)))))))
(defun go-mode-indent-line () (defun go-mode-indent-line ()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment