diff options
Diffstat (limited to 'misc/emacs/go-mode.el')
-rw-r--r-- | misc/emacs/go-mode.el | 63 |
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 |