summaryrefslogtreecommitdiff
path: root/misc/emacs/go-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'misc/emacs/go-mode.el')
-rw-r--r--misc/emacs/go-mode.el63
1 files changed, 50 insertions, 13 deletions
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 75b28ac73..6333ff966 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -7,6 +7,7 @@
(require 'cl)
(require 'etags)
(require 'ffap)
+(require 'find-file)
(require 'ring)
(require 'url)
@@ -61,6 +62,7 @@
;; macro.
(if nil
(declare-function go--position-bytes "go-mode" (point)))
+
;; XEmacs unfortunately does not offer position-bytes. We can fall
;; back to just using (point), but it will be incorrect as soon as
;; multibyte characters are being used.
@@ -167,6 +169,13 @@ from https://github.com/bradfitz/goimports."
:type 'string
:group 'go)
+(defcustom go-other-file-alist
+ '(("_test\\.go\\'" (".go"))
+ ("\\.go\\'" ("_test.go")))
+ "See the documentation of `ff-other-file-alist' for details."
+ :type '(repeat (list regexp (choice (repeat string) function)))
+ :group 'go)
+
(defface go-coverage-untracked
'((t (:foreground "#505050")))
"Coverage color of untracked code."
@@ -249,22 +258,23 @@ For mode=set, all covered lines will have this weight."
"Syntax table for Go mode.")
(defun go--build-font-lock-keywords ()
- ;; we cannot use 'symbols in regexp-opt because emacs <24 doesn't
- ;; understand that
+ ;; we cannot use 'symbols in regexp-opt because GNU Emacs <24
+ ;; doesn't understand that
(append
`((,(go--regexp-enclose-in-symbol (regexp-opt go-mode-keywords t)) . font-lock-keyword-face)
- (,(go--regexp-enclose-in-symbol (regexp-opt go-builtins t)) . font-lock-builtin-face)
+ (,(concat "\\(" (go--regexp-enclose-in-symbol (regexp-opt go-builtins t)) "\\)[[:space:]]*(") 1 font-lock-builtin-face)
(,(go--regexp-enclose-in-symbol (regexp-opt go-constants t)) . font-lock-constant-face)
(,go-func-regexp 1 font-lock-function-name-face)) ;; function (not method) name
(if go-fontify-function-calls
`((,(concat "\\(" go-identifier-regexp "\\)[[:space:]]*(") 1 font-lock-function-name-face) ;; function call/method name
(,(concat "[^[:word:][:multibyte:]](\\(" go-identifier-regexp "\\))[[:space:]]*(") 1 font-lock-function-name-face)) ;; bracketed function call
- `((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name
+ `((,go-func-meth-regexp 2 font-lock-function-name-face))) ;; method name
`(
- (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*\\([^[:space:]]+\\)") 1 font-lock-type-face) ;; types
- (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
+ ("\\(`[^`]*`\\)" 1 font-lock-multiline) ;; raw string literal, needed for font-lock-syntactic-keywords
+ (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]+\\([^[:space:]]+\\)") 1 font-lock-type-face) ;; types
+ (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]+" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
(,(concat "[^[:word:][:multibyte:]]\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices
(,(concat "\\(" go-identifier-regexp "\\)" "{") 1 font-lock-type-face)
(,(concat (go--regexp-enclose-in-symbol "map") "\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type
@@ -281,6 +291,14 @@ For mode=set, all covered lines will have this weight."
(,(concat "^[[:space:]]*\\(" go-label-regexp "\\)[[:space:]]*:\\(\\S.\\|$\\)") 1 font-lock-constant-face) ;; Labels and compound literal fields
(,(concat (go--regexp-enclose-in-symbol "\\(goto\\|break\\|continue\\)") "[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue
+(defconst go--font-lock-syntactic-keywords
+ ;; Override syntax property of raw string literal contents, so that
+ ;; backslashes have no special meaning in ``. Used in Emacs 23 or older.
+ '((go--match-raw-string-literal
+ (1 (7 . ?`))
+ (2 (15 . nil)) ;; 15 = "generic string"
+ (3 (7 . ?`)))))
+
(defvar go-mode-map
(let ((m (make-sparse-keymap)))
(define-key m "}" #'go-mode-insert-and-indent)
@@ -349,6 +367,18 @@ STOP-AT-STRING is not true, over strings."
(- (point-max)
(point-min))))
+(defun go--match-raw-string-literal (end)
+ "Search for a raw string literal. Set point to the end of the
+occurence found on success. Returns nil on failure."
+ (when (search-forward "`" end t)
+ (goto-char (match-beginning 0))
+ (if (go-in-string-or-comment-p)
+ (progn (goto-char (match-end 0))
+ (go--match-raw-string-literal end))
+ (when (looking-at "\\(`\\)\\([^`]*\\)\\(`\\)")
+ (goto-char (match-end 0))
+ t))))
+
(defun go-previous-line-has-dangling-op-p ()
"Returns non-nil if the current line is a continuation line."
(let* ((cur-line (line-number-at-pos))
@@ -450,8 +480,9 @@ current line will be returned."
(goto-char (- (point-max) pos))))))
(defun go-beginning-of-defun (&optional count)
- (unless count (setq count 1))
- (let ((first t) failure)
+ (setq count (or count 1))
+ (let ((first t)
+ failure)
(dotimes (i (abs count))
(while (and (not failure)
(or first (go-in-string-or-comment-p)))
@@ -513,7 +544,7 @@ The following extra functions are defined:
If you want to automatically run `gofmt' before saving a file,
add the following hook to your emacs configuration:
-\(add-hook 'before-save-hook 'gofmt-before-save)
+\(add-hook 'before-save-hook #'gofmt-before-save)
If you want to use `godef-jump' instead of etags (or similar),
consider binding godef-jump to `M-.', which is the default key
@@ -532,7 +563,8 @@ If you're looking for even more integration with Go, namely
on-the-fly syntax checking, auto-completion and snippets, it is
recommended that you look at goflymake
\(https://github.com/dougm/goflymake), gocode
-\(https://github.com/nsf/gocode) and yasnippet-go
+\(https://github.com/nsf/gocode), go-eldoc
+\(github.com/syohex/emacs-go-eldoc) and yasnippet-go
\(https://github.com/dominikh/yasnippet-go)"
;; Font lock
@@ -553,11 +585,16 @@ recommended that you look at goflymake
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(if (boundp 'syntax-propertize-function)
- (set (make-local-variable 'syntax-propertize-function) #'go-propertize-syntax))
+ (set (make-local-variable 'syntax-propertize-function) #'go-propertize-syntax)
+ (set (make-local-variable 'font-lock-syntactic-keywords)
+ go--font-lock-syntactic-keywords)
+ (set (make-local-variable 'font-lock-multiline) t))
(set (make-local-variable 'go-dangling-cache) (make-hash-table :test 'eql))
(add-hook 'before-change-functions (lambda (x y) (setq go-dangling-cache (make-hash-table :test 'eql))) t t)
+ ;; ff-find-other-file
+ (setq ff-other-file-alist 'go-other-file-alist)
(setq imenu-generic-expression
'(("type" "^type *\\([^ \t\n\r\f]*\\)" 1)
@@ -992,7 +1029,7 @@ description at POINT."
"-f"
(file-truename (buffer-file-name (go--coverage-origin-buffer)))
"-o"
- (number-to-string (go--position-bytes (point))))
+ (number-to-string (go--position-bytes point)))
(with-current-buffer outbuf
(split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")))))
@@ -1108,7 +1145,7 @@ divisor for FILE-NAME."
(start-line start-column end-line end-column num count)
(mapcar #'string-to-number rest)
- (when (and (string= (file-name-nondirectory file) file-name))
+ (when (string= (file-name-nondirectory file) file-name)
(if (> count max-count)
(setq max-count count))
(push (make-go--covered :start-line start-line