diff options
author | Hilko Bengen <bengen@debian.org> | 2017-04-02 11:35:01 +0200 |
---|---|---|
committer | Hilko Bengen <bengen@debian.org> | 2017-04-02 11:35:10 +0200 |
commit | bf9ce4c27346c921b8b70b9650bc74e77a9ff00e (patch) | |
tree | d8c2dcf10ceff79fd2e4917538cae98036c4618c /go-mode.el | |
parent | 468815f7da22ed21c824c8edd60e121e7ebfba70 (diff) | |
parent | 99b40584eb81185d410b46742b6bd8016e6d75a8 (diff) |
Merge tag 'upstream/1.5.0'
Upstream version 1.5.0
Diffstat (limited to 'go-mode.el')
-rw-r--r-- | go-mode.el | 312 |
1 files changed, 126 insertions, 186 deletions
@@ -1,11 +1,13 @@ ;;; go-mode.el --- Major mode for the Go programming language -;; Copyright 2013 The go-mode Authors. All rights reserved. +;;; Commentary: + +;; Copyright 2013 The go-mode Authors. All rights reserved. ;; Use of this source code is governed by a BSD-style ;; license that can be found in the LICENSE file. ;; Author: The go-mode Authors -;; Version: 1.4.0 +;; Version: 1.5.0 ;; Keywords: languages go ;; URL: https://github.com/dominikh/go-mode.el ;; @@ -20,35 +22,14 @@ (require 'find-file) (require 'ring) (require 'url) +(require 'xref nil :noerror) ; xref is new in Emacs 25.1 -;; XEmacs compatibility guidelines -;; - Minimum required version of XEmacs: 21.5.32 -;; - Feature that cannot be backported: POSIX character classes in -;; regular expressions -;; - Functions that could be backported but won't because 21.5.32 -;; covers them: plenty. -;; - Features that are still partly broken: -;; - godef will not work correctly if multibyte characters are -;; being used -;; - Fontification will not handle unicode correctly -;; -;; - Do not use \_< and \_> regexp delimiters directly; use -;; go--regexp-enclose-in-symbol -;; -;; - The character `_` must not be a symbol constituent but a -;; character constituent -;; -;; - Do not use process-lines -;; -;; - Use go--old-completion-list-style when using a plain list as the -;; collection for completing-read -;; -;; - Use go--position-bytes instead of position-bytes -(defmacro go--xemacs-p () - (featurep 'xemacs)) -(defmacro go--has-syntax-propertize-p () - (boundp 'syntax-propertize-function)) +(eval-when-compile + (defmacro go--forward-word (&optional arg) + (if (fboundp 'forward-word-strictly) + `(forward-word-strictly ,arg) + `(forward-word ,arg)))) (defun go--delete-whole-line (&optional arg) "Delete the current line without putting it in the `kill-ring'. @@ -76,43 +57,6 @@ function." (delete-region (progn (forward-visible-line 0) (point)) (progn (forward-visible-line arg) (point)))))) -;; declare-function is an empty macro that only byte-compile cares -;; about. Wrap in always false if to satisfy Emacsen without that -;; 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. -(if (fboundp 'position-bytes) - (defalias 'go--position-bytes #'position-bytes) - (defun go--position-bytes (point) point)) - -(defun go--old-completion-list-style (list) - (mapcar (lambda (x) (cons x nil)) list)) - -;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not, so -;; copy its definition for those. -(if (not (fboundp 'prog-mode)) - (define-derived-mode prog-mode fundamental-mode "Prog" - "Major mode for editing source code." - (set (make-local-variable 'require-final-newline) mode-require-final-newline) - (set (make-local-variable 'parse-sexp-ignore-comments) t) - (setq bidi-paragraph-direction 'left-to-right))) - -(defun go--regexp-enclose-in-symbol (s) - "Enclose S as regexp symbol. -XEmacs does not support \\_<, GNU Emacs does. In GNU Emacs we -make extensive use of \\_< to support unicode in identifiers. -Until we come up with a better solution for XEmacs, this solution -will break fontification in XEmacs for identifiers such as -\"typeµ\". XEmacs will consider \"type\" a keyword, GNU Emacs -won't." - (if (go--xemacs-p) - (concat "\\<" s "\\>") - (concat "\\_<" s "\\_>"))) - (defun go-goto-opening-parenthesis (&optional _legacy-unused) "Move up one level of parentheses." ;; The old implementation of go-goto-opening-parenthesis had an @@ -126,14 +70,20 @@ won't." (defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]") +(defconst go--max-dangling-operator-length 2 + "The maximum length of dangling operators. +This must be at least the length of the longest string matched by +‘go-dangling-operators-regexp.’, and must be updated whenever +that constant is changed.") + (defconst go-identifier-regexp "[[:word:][:multibyte:]]+") (defconst go-type-name-no-prefix-regexp "\\(?:[[:word:][:multibyte:]]+\\.\\)?[[:word:][:multibyte:]]+") (defconst go-qualified-identifier-regexp (concat go-identifier-regexp "\\." go-identifier-regexp)) (defconst go-label-regexp go-identifier-regexp) (defconst go-type-regexp "[[:word:][:multibyte:]*]+") -(defconst go-func-regexp (concat (go--regexp-enclose-in-symbol "func") "\\s *\\(" go-identifier-regexp "\\)")) +(defconst go-func-regexp (concat "\\_<func\\_>\\s *\\(" go-identifier-regexp "\\)")) (defconst go-func-meth-regexp (concat - (go--regexp-enclose-in-symbol "func") "\\s *\\(?:(\\s *" + "\\_<func\\_>\\s *\\(?:(\\s *" "\\(" go-identifier-regexp "\\s +\\)?" go-type-regexp "\\s *)\\s *\\)?\\(" go-identifier-regexp @@ -199,7 +149,7 @@ point to the wrapper script." (defcustom gofmt-command "gofmt" "The 'gofmt' command. Some users may replace this with 'goimports' -from https://github.com/bradfitz/goimports." +from https://golang.org/x/tools/cmd/goimports." :type 'string :group 'go) @@ -234,14 +184,13 @@ a `before-save-hook'." :group 'go) (defcustom go-packages-function 'go-packages-native - "Function called by `go-packages' to determine the list of -available packages. This is used in e.g. tab completion in -`go-import-add'. + "Function called by `go-packages' to determine the list of available packages. +This is used in e.g. tab completion in `go-import-add'. This package provides two functions: `go-packages-native' uses elisp to find all .a files in all /pkg/ directories. `go-packages-go-list' uses 'go list all' to determine all Go -packages. `go-packages-go-list' generally produces more accurate +packages. `go-packages-go-list' generally produces more accurate results, but can be slower than `go-packages-native'." :type 'function :package-version '(go-mode . 1.4.0) @@ -254,30 +203,31 @@ results, but can be slower than `go-packages-native'." "Functions to call in sequence to detect a project's GOPATH. The functions in this list will be called one after another, -until a function returns non-nil. The order of the functions in +until a function returns non-nil. The order of the functions in this list is important, as some project layouts may superficially -look like others. For example, a subset of wgo projects look like -gb projects. That's why we need to detect wgo first, to avoid +look like others. For example, a subset of wgo projects look like +gb projects. That's why we need to detect wgo first, to avoid mis-identifying them as gb projects." :type '(repeat function) :group 'go) (defcustom godoc-command "go doc" - "Which executable to use for `godoc'. This can either be -'godoc' or 'go doc', both as an absolute path or an executable in -PATH." + "Which executable to use for `godoc'. +This can either be 'godoc' or 'go doc', both as an absolute path +or an executable in PATH." :type 'string :group 'go) (defcustom godoc-and-godef-command "godoc" - "Which executable to use for `godoc' in -`godoc-and-godef-command'. Must be 'godoc' and not 'go doc' and -can be an absolute path or an executable in PATH." + "Which executable to use for `godoc' in `godoc-and-godef-command'. +Must be 'godoc' and not 'go doc' and can be an absolute path or +an executable in PATH." :type 'string :group 'go) (defcustom godoc-use-completing-read nil - "Provide auto-completion for godoc. Only really desirable when using `godoc' instead of `go doc'." + "Provide auto-completion for godoc. +Only really desirable when using `godoc' instead of `go doc'." :type 'boolean :group 'godoc) @@ -286,24 +236,24 @@ can be an absolute path or an executable in PATH." identifier at a given position. This package provides two functions: `godoc-and-godef' uses a -combination of godef and godoc to find the documentation. This -approach has several caveats. See its documentation for more -information. The second function, `godoc-gogetdoc' uses an +combination of godef and godoc to find the documentation. This +approach has several caveats. See its documentation for more +information. The second function, `godoc-gogetdoc' uses an additional tool that correctly determines the documentation for -any identifier. It provides better results than -`godoc-and-godef'. " +any identifier. It provides better results than +`godoc-and-godef'." :type 'function :group 'godoc) (defun godoc-and-godef (point) - "Use a combination of godef and godoc to guess the documentation. + "Use a combination of godef and godoc to guess the documentation at POINT. Due to a limitation in godoc, it is not possible to differentiate between functions and methods, which may cause `godoc-at-point' -to display more documentation than desired. Furthermore, it +to display more documentation than desired. Furthermore, it doesn't work on package names or variables. -Consider using godoc-gogetdoc instead for more accurate results." +Consider using ‘godoc-gogetdoc’ instead for more accurate results." (condition-case nil (let* ((output (godef--call point)) (file (car output)) @@ -320,14 +270,14 @@ Consider using godoc-gogetdoc instead for more accurate results." (file-error (message "Could not run godef binary")))) (defun godoc-gogetdoc (point) - "Use the gogetdoc tool to find the documentation for an identifier. + "Use the gogetdoc tool to find the documentation for an identifier at POINT. You can install gogetdoc with 'go get -u github.com/zmb3/gogetdoc'." (if (not (buffer-file-name (go--coverage-origin-buffer))) ;; TODO: gogetdoc supports unsaved files, but not introducing ;; new artifical files, so this limitation will stay for now. (error "Cannot use gogetdoc on a buffer without a file name")) - (let ((posn (format "%s:#%d" (shell-quote-argument (file-truename buffer-file-name)) (1- (go--position-bytes point)))) + (let ((posn (format "%s:#%d" (shell-quote-argument (file-truename buffer-file-name)) (1- (position-bytes point)))) (out (godoc--get-buffer "<at point>"))) (with-current-buffer (get-buffer-create "*go-gogetdoc-input*") (setq buffer-read-only nil) @@ -429,15 +379,14 @@ For mode=set, all covered lines will have this weight." (modify-syntax-entry ?= "." st) (modify-syntax-entry ?< "." st) (modify-syntax-entry ?> "." st) - (modify-syntax-entry ?/ (if (go--xemacs-p) ". 1456" ". 124b") st) + (modify-syntax-entry ?/ ". 124b" st) (modify-syntax-entry ?* ". 23" st) (modify-syntax-entry ?\n "> b" st) (modify-syntax-entry ?\" "\"" st) (modify-syntax-entry ?\' "\"" st) (modify-syntax-entry ?` "\"" st) (modify-syntax-entry ?\\ "\\" st) - ;; It would be nicer to have _ as a symbol constituent, but that - ;; would trip up XEmacs, which does not support the \_< anchor + ;; TODO make _ a symbol constituent now that xemacs is gone (modify-syntax-entry ?_ "w" st) st) @@ -450,9 +399,9 @@ For mode=set, all covered lines will have this weight." `((go--match-func ,@(mapcar (lambda (x) `(,x font-lock-type-face)) (number-sequence 1 go--font-lock-func-param-num-groups))) - (,(go--regexp-enclose-in-symbol (regexp-opt go-mode-keywords t)) . font-lock-keyword-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) + (,(concat "\\_<" (regexp-opt go-mode-keywords t) "\\_>") . font-lock-keyword-face) + (,(concat "\\(\\_<" (regexp-opt go-builtins t) "\\_>\\)[[:space:]]*(") 1 font-lock-builtin-face) + (,(concat "\\_<" (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 @@ -462,29 +411,21 @@ For mode=set, all covered lines will have this weight." `( ("\\(`[^`]*`\\)" 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 "\\_<type\\_>[[:space:]]+\\([^[:space:](]+\\)") 1 font-lock-type-face) ;; types + (,(concat "\\_<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 - (,(concat (go--regexp-enclose-in-symbol "map") "\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type - (,(concat (go--regexp-enclose-in-symbol "chan") "[[:space:]]*\\(?:<-[[:space:]]*\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type - (,(concat (go--regexp-enclose-in-symbol "\\(?:new\\|make\\)") "\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type + (,(concat "\\_<map\\_>\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type + (,(concat "\\_<map\\_>\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type + (,(concat "\\_<chan\\_>[[:space:]]*\\(?:<-[[:space:]]*\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type + (,(concat "\\_<\\(?:new\\|make\\)\\_>\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type ;; TODO do we actually need this one or isn't it just a function call? (,(concat "\\.\\s *(" go-type-name-regexp) 1 font-lock-type-face) ;; Type conversion ;; Like the original go-mode this also marks compound literal ;; fields. There, it was marked as to fix, but I grew quite ;; accustomed to it, so it'll stay for now. (,(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 . ?`))))) + (,(concat "\\_<\\(goto\\|break\\|continue\\)\\_>[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue (let ((m (define-prefix-command 'go-goto-map))) (define-key m "a" #'go-goto-arguments) @@ -506,7 +447,7 @@ For mode=set, all covered lines will have this weight." (define-key m (kbd "C-c C-d") #'godef-describe) (define-key m (kbd "C-c C-f") 'go-goto-map) m) - "Keymap used by go-mode.") + "Keymap used by ‘go-mode’.") (easy-menu-define go-mode-menu go-mode-map "Menu for Go mode." @@ -561,13 +502,13 @@ STOP-AT-STRING is not true, over strings." (let (pos (start-pos (point))) (skip-chars-backward "\n\s\t") (if (and (save-excursion (beginning-of-line) (go-in-string-p)) - (looking-back "`") + (= (char-before) ?`) (not stop-at-string)) (backward-char)) (if (and (go-in-string-p) (not stop-at-string)) (go-goto-beginning-of-string-or-comment)) - (if (looking-back "\\*/") + (if (looking-back "\\*/" (line-beginning-position)) (backward-char)) (if (go-in-comment-p) (go-goto-beginning-of-string-or-comment)) @@ -587,19 +528,6 @@ 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. Return nil on failure." - (unless (go-in-string-or-comment-p) - (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 () "Return non-nil if the current line is a continuation line." (let* ((cur-line (line-number-at-pos)) @@ -608,7 +536,8 @@ Set point to the end of the occurence found on success. Return nil on failure." (save-excursion (beginning-of-line) (go--backward-irrelevant t) - (setq val (looking-back go-dangling-operators-regexp)) + (setq val (looking-back go-dangling-operators-regexp + (- (point) go--max-dangling-operator-length))) (if (not (go--buffer-narrowed-p)) (puthash cur-line val go-dangling-cache)))) val)) @@ -618,9 +547,9 @@ Set point to the end of the occurence found on success. Return nil on failure." function definition. We do this by first calling (beginning-of-defun), which will take -us to the start of *some* function. We then look for the opening +us to the start of *some* function. We then look for the opening curly brace of that function and compare its position against the -curly brace we are checking. If they match, we return non-nil." +curly brace we are checking. If they match, we return non-nil." (if (= (char-after) ?\{) (save-excursion (let ((old-point (point)) @@ -663,7 +592,9 @@ current line will be returned." (if (go-previous-line-has-dangling-op-p) (- (current-indentation) tab-width) (go--indentation-for-opening-parenthesis))) - ((progn (go--backward-irrelevant t) (looking-back go-dangling-operators-regexp)) + ((progn (go--backward-irrelevant t) + (looking-back go-dangling-operators-regexp + (- (point) go--max-dangling-operator-length))) ;; only one nesting for all dangling operators in one operation (if (go-previous-line-has-dangling-op-p) (current-indentation) @@ -738,7 +669,8 @@ current line will be returned." (skip-chars-forward "^{") (forward-char) (or (go-in-string-or-comment-p) - (looking-back "\\(struct\\|interface\\)\\s-*{")))) + (looking-back "\\(struct\\|interface\\)\\s-*{" + (line-beginning-position))))) (setq orig-level (go-paren-level)) (while (>= (go-paren-level) orig-level) (skip-chars-forward "^}") @@ -792,7 +724,7 @@ parenthesis before a comma, it stops at it." "Search for identifiers used as type names from a function parameter list, and set the identifier positions as the results of last search. Return t if search succeeded." - (when (re-search-forward (go--regexp-enclose-in-symbol "func") end t) + (when (re-search-forward "\\_<func\\_>" end t) (let ((regions (go--match-func-type-names end))) (if (null regions) ;; Nothing to highlight. This can happen if the current func @@ -823,8 +755,8 @@ of last search. Return t if search succeeded." (nconc regions (go--match-function-result end)))))) (defun go--parameter-list-type (end) - "Return `present' if the parameter list has names, or `absent' if -not, assuming point is at the beginning of a parameter list, just + "Return `present' if the parameter list has names, or `absent' if not. +Assumes point is at the beginning of a parameter list, just after '('." (save-excursion (skip-chars-forward "[:space:]\n" end) @@ -844,7 +776,7 @@ after '('." (defconst go--parameter-type-regexp (concat go--opt-dotdotdot-regexp "[[:space:]*\n]*\\(" go-type-name-no-prefix-regexp "\\)[[:space:]\n]*\\([,)]\\|\\'\\)")) (defconst go--func-type-in-parameter-list-regexp - (concat go--opt-dotdotdot-regexp "[[:space:]*\n]*\\(" (go--regexp-enclose-in-symbol "func") "\\)")) + (concat go--opt-dotdotdot-regexp "[[:space:]*\n]*\\(\\_<func\\_>" "\\)")) (defun go--match-parameters-common (identifier-regexp end) (let ((acc ()) @@ -955,6 +887,12 @@ Function result is a unparenthesized type or a parameter list." (go--match-parameter-list end)) (t nil))) +(defun go--reset-dangling-cache-before-change (&optional _beg _end) + "Reset `go-dangling-cache'. + +This is intended to be called from `before-change-functions'." + (setq go-dangling-cache (make-hash-table :test 'eql))) + ;;;###autoload (define-derived-mode go-mode prog-mode "Go" "Major mode for editing Go source text. @@ -1036,11 +974,7 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode (set (make-local-variable 'end-of-defun-function) #'go-end-of-defun) (set (make-local-variable 'parse-sexp-lookup-properties) t) - (if (go--has-syntax-propertize-p) - (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 'syntax-propertize-function) #'go-propertize-syntax) (if (boundp 'electric-indent-chars) (set (make-local-variable 'electric-indent-chars) '(?\n ?} ?\)))) @@ -1048,7 +982,7 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode (set (make-local-variable 'compilation-error-screen-columns) nil) (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) + (add-hook 'before-change-functions #'go--reset-dangling-cache-before-change t t) ;; ff-find-other-file (setq ff-other-file-alist 'go-other-file-alist) @@ -1101,7 +1035,7 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode (goto-char (point-min)) (while (not (eobp)) (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)") - (error "invalid rcs patch or internal error in go--apply-rcs-patch")) + (error "Invalid rcs patch or internal error in go--apply-rcs-patch")) (forward-line) (let ((action (match-string 1)) (from (string-to-number (match-string 2))) @@ -1122,7 +1056,7 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode (cl-incf line-offset len) (go--delete-whole-line len))) (t - (error "invalid rcs patch or internal error in go--apply-rcs-patch"))))))))) + (error "Invalid rcs patch or internal error in go--apply-rcs-patch"))))))))) (defun gofmt--is-goimports-p () (string-equal (file-name-base gofmt-command) "goimports")) @@ -1152,7 +1086,11 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode (when (and (gofmt--is-goimports-p) buffer-file-name) (setq our-gofmt-args (append our-gofmt-args - (list "-srcdir" (file-name-directory (file-truename buffer-file-name)))))) + ;; srcdir, despite its name, supports + ;; accepting a full path, and some features + ;; of goimports rely on knowing the full + ;; name. + (list "-srcdir" (file-truename buffer-file-name))))) (setq our-gofmt-args (append our-gofmt-args gofmt-args (list "-w" tmpfile))) @@ -1205,9 +1143,9 @@ with goflymake \(see URL `https://github.com/dougm/goflymake'), gocode ;;;###autoload (defun gofmt-before-save () "Add this to .emacs to run gofmt on the current buffer when saving: - (add-hook 'before-save-hook 'gofmt-before-save). +\(add-hook 'before-save-hook 'gofmt-before-save). -Note that this will cause go-mode to get loaded the first time +Note that this will cause ‘go-mode’ to get loaded the first time you save any file, kind of defeating the point of autoloading." (interactive) @@ -1217,11 +1155,11 @@ you save any file, kind of defeating the point of autoloading." "Read a godoc query from the minibuffer." (if godoc-use-completing-read (completing-read "godoc; " - (go--old-completion-list-style (go-packages)) nil nil nil 'go-godoc-history) + (go-packages) nil nil nil 'go-godoc-history) (read-from-minibuffer "godoc: " nil nil nil 'go-godoc-history))) (defun godoc--get-buffer (query) - "Get an empty buffer for a godoc query." + "Get an empty buffer for a godoc QUERY." (let* ((buffer-name (concat "*godoc " query "*")) (buffer (get-buffer buffer-name))) ;; Kill the existing buffer if it already exists. @@ -1246,7 +1184,7 @@ you save any file, kind of defeating the point of autoloading." ;;;###autoload (defun godoc (query) - "Show Go documentation for QUERY, much like M-x man." + "Show Go documentation for QUERY, much like \\<go-mode-map>\\[man]." (interactive (list (godoc--read-query))) (go--godoc query godoc-command)) @@ -1317,7 +1255,7 @@ declaration." (go-play-region (point-min) (point-max))) (defun go-play-region (start end) - "Send the region to the Playground. + "Send the region between START and END to the Playground. If non-nil `go-play-browse-function' is called with the Playground URL." (interactive "r") @@ -1381,7 +1319,7 @@ uncommented, otherwise a new import will be added." (interactive (list current-prefix-arg - (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go--old-completion-list-style (go-packages)))))) + (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go-packages))))) (save-excursion (let (as line import-start) (if arg @@ -1440,8 +1378,8 @@ If IGNORE-CASE is non-nil, the comparison is case-insensitive." (funcall go-packages-function)) (defun go-packages-native () - "Return a list of all installed Go packages. It looks for -archive files in /pkg/" + "Return a list of all installed Go packages. +It looks for archive files in /pkg/." (sort (delete-dups (cl-mapcan @@ -1460,7 +1398,7 @@ archive files in /pkg/" #'string<)) (defun go-packages-go-list () - "Return a list of all Go packages, using `go list'" + "Return a list of all Go packages, using `go list'." (process-lines go-command "list" "-e" "all")) (defun go-unused-imports-lines () @@ -1523,29 +1461,27 @@ visit FILENAME and go to line LINE and column COLUMN." (defun godef--call (point) "Call godef, acquiring definition position and expression description at POINT." - (if (go--xemacs-p) - (error "godef does not reliably work in XEmacs, expect bad results")) (if (not (buffer-file-name (go--coverage-origin-buffer))) (error "Cannot use godef on a buffer without a file name") - (let ((outbuf (get-buffer-create "*godef*")) + (let ((outbuf (generate-new-buffer "*godef*")) (coding-system-for-read 'utf-8) (coding-system-for-write 'utf-8)) - (with-current-buffer outbuf - (erase-buffer)) - (call-process-region (point-min) - (point-max) - godef-command - nil - outbuf - nil - "-i" - "-t" - "-f" - (file-truename (buffer-file-name (go--coverage-origin-buffer))) - "-o" - (number-to-string (go--position-bytes point))) - (with-current-buffer outbuf - (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n"))))) + (prog2 + (call-process-region (point-min) + (point-max) + godef-command + nil + outbuf + nil + "-i" + "-t" + "-f" + (file-truename (buffer-file-name (go--coverage-origin-buffer))) + "-o" + (number-to-string (position-bytes point))) + (with-current-buffer outbuf + (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")) + (kill-buffer outbuf))))) (defun godef--successful-p (output) (not (or (string= "-" output) @@ -1580,7 +1516,10 @@ description at POINT." (if (not (godef--successful-p file)) (message "%s" (godef--error file)) (push-mark) - (ring-insert find-tag-marker-ring (point-marker)) + (if (eval-when-compile (fboundp 'xref-push-marker-stack)) + ;; TODO: Integrate this facility with XRef. + (xref-push-marker-stack) + (ring-insert find-tag-marker-ring (point-marker))) (godef--find-file-line-column file other-window))) (file-error (message "Could not run godef binary")))) @@ -1758,7 +1697,7 @@ If ARG is non-nil, anonymous functions are ignored." ;; should search forward instead. (when (not (looking-at "\\<func\\>")) (re-search-forward "\\<func\\>" nil t) - (forward-word -1)) + (go--forward-word -1)) ;; If we have landed at an anonymous function, it is possible that we ;; were not inside it but below it. If we were not inside it, we should @@ -1789,7 +1728,8 @@ If ARG is non-nil, anonymous functions are ignored." (skip-chars-forward "^{") (forward-char) (or (go-in-string-or-comment-p) - (looking-back "\\(struct\\|interface\\)\\s-*{")))) + (looking-back "\\(struct\\|interface\\)\\s-*{" + (line-beginning-position))))) (backward-char)) (defun go--in-function-p (compare-point) @@ -1801,7 +1741,7 @@ If ARG is non-nil, anonymous functions are ignored." (go--goto-opening-curly-brace) (unless (looking-at "{") - (error "expected to be looking at opening curly brace")) + (error "Expected to be looking at opening curly brace")) (forward-list 1) (and (>= compare-point start) (<= compare-point (point)))))) @@ -1824,7 +1764,7 @@ If ARG is non-nil, anonymous functions are skipped." (when (looking-at "\\<func (") (setq words 3 chars 2)) - (forward-word words) + (go--forward-word words) (forward-char chars) (when (looking-at "Test") (forward-char 4))))) @@ -1835,7 +1775,7 @@ If ARG is non-nil, anonymous functions are skipped." If ARG is non-nil, anonymous functions are skipped." (interactive "P") (go-goto-function-name arg) - (forward-word 1) + (go--forward-word 1) (forward-char 1)) (defun go--goto-return-values (&optional arg) @@ -1870,7 +1810,7 @@ If ARG is non-nil, anonymous functions are skipped." If there is none, add parenthesis to add one. Anonymous functions cannot have method receivers, so when this is called -interactively anonymous functions will be skipped. If called programmatically, +interactively anonymous functions will be skipped. If called programmatically, an error is raised unless ARG is non-nil." (interactive "P") @@ -1892,7 +1832,7 @@ an error is raised unless ARG is non-nil." If there is none, add one beginning with the name of the current function. Anonymous functions do not have docstrings, so when this is called -interactively anonymous functions will be skipped. If called programmatically, +interactively anonymous functions will be skipped. If called programmatically, an error is raised unless ARG is non-nil." (interactive "P") @@ -1930,7 +1870,7 @@ an error is raised unless ARG is non-nil." "Return the name of the surrounding function. If ARG is non-nil, anonymous functions will be ignored and the -name returned will be that of the top-level function. If ARG is +name returned will be that of the top-level function. If ARG is nil and the surrounding function is anonymous, nil will be returned." (when (or (not (go--in-anonymous-funcion-p)) |