mirror of
https://github.com/golang/go
synced 2024-11-25 06:07:58 -07:00
Update Emacs go-mode for new semicolon rule.
Fixes #415. R=rsc CC=golang-dev https://golang.org/cl/183104
This commit is contained in:
parent
cfbee34a27
commit
6712cf365b
@ -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 ()
|
||||
|
Loading…
Reference in New Issue
Block a user