[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/go-mode d6aa01a 287/495: Merge branch 'movement'
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/go-mode d6aa01a 287/495: Merge branch 'movement' |
Date: |
Sat, 7 Aug 2021 09:05:33 -0400 (EDT) |
branch: elpa/go-mode
commit d6aa01a1dc299efd1ab1470b2c33b39deb8bd315
Merge: dccb56c abc56d4
Author: Dominik Honnef <dominik@honnef.co>
Commit: Dominik Honnef <dominik@honnef.co>
Merge branch 'movement'
This adds new functions for jumping to various parts of a function's
signature:
- go-goto-arguments
- go-goto-docstring
- go-goto-function
- go-goto-function-name
- go-goto-return-values
- go-goto-method-receiver
All of these functions are aware of anonymous functions.
go-goto-docstring and go-goto-method-receiver, however, will skip over
anonymous functions if called interactively.
All of these functions accept a prefix argument to force them to skip
over anonymous functions.
All of these functions, and the existing go-goto-imports, are added to a
new prefix keymap, bound to `C-c C-g`.
Closes gh-117
---
README.md | 18 ++++-
go-mode.el | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 6e5a780..826c725 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,8 @@ the following extra features to provide an improved
experience:
- `go-download-play` to download a Playground entry into a new
buffer
- Managing imports
- - A function for jumping to the file's imports (`go-goto-imports`)
+ - A function for jumping to the file's imports (`go-goto-imports` -
+ `C-c C-g i`)
- A function for adding imports, including tab completion
(`go-import-add`, bound to `C-c C-a`)
- A function for removing or commenting unused imports
@@ -40,6 +41,21 @@ the following extra features to provide an improved
experience:
- Basic support for imenu (functions and variables)
- Built-in support for displaying code coverage as calculated by `go
test` (`go-coverage`)
+- Several functions for jumping to and manipulating the individual
+ parts of function signatures. These functions support anonymous
+ functions, but are smart enough to skip them when required (e.g.
+ when jumping to a method receiver or docstring.)
+ - Jump to the argument list (`go-goto-arguments` - `C-c C-g a`)
+ - Jump to the docstring, create it if it does not exist yet
+ (`go-goto-docstring` - `C-c C-g d`).
+ - Jump to the function keyword (`go-goto-function` - `C-c C-g f`)
+ - Jump to the function name (`go-goto-function-name` - `C-c C-g n`)
+ - Jump to the return values (`go-goto-return-values` - `C-c C-g r`)
+ - Jump to the method receiver, adding a pair of parentheses if no
+ method receiver exists (`go-goto-method-receiver` - `C-c C-g m`).
+
+ All of these functions accept a prefix argument (`C-u`), causing
+ them to skip anonymous functions.
# Installation
diff --git a/go-mode.el b/go-mode.el
index 851b937..bf5505e 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -365,6 +365,15 @@ For mode=set, all covered lines will have this weight."
(2 (15 . nil)) ;; 15 = "generic string"
(3 (7 . ?`)))))
+(let ((m (define-prefix-command 'go-goto-map)))
+ (define-key m "a" #'go-goto-arguments)
+ (define-key m "d" #'go-goto-docstring)
+ (define-key m "f" #'go-goto-function)
+ (define-key m "i" #'go-goto-imports)
+ (define-key m "m" #'go-goto-method-receiver)
+ (define-key m "n" #'go-goto-function-name)
+ (define-key m "r" #'go-goto-return-values))
+
(defvar go-mode-map
(let ((m (make-sparse-keymap)))
(define-key m "}" #'go-mode-insert-and-indent)
@@ -376,6 +385,7 @@ For mode=set, all covered lines will have this weight."
(define-key m (kbd "C-c C-j") #'godef-jump)
(define-key m (kbd "C-x 4 C-c C-j") #'godef-jump-other-window)
(define-key m (kbd "C-c C-d") #'godef-describe)
+ (define-key m (kbd "C-c C-g") 'go-goto-map)
m)
"Keymap used by Go mode to implement electric keys.")
@@ -600,7 +610,7 @@ current line will be returned."
;; breaks if there's a comment between the struct/interface keyword and
;; bracket, like this:
;;
- ;; struct /* why? */ {
+ ;; struct /* why? */ {
(while (progn
(skip-chars-forward "^{")
(forward-char)
@@ -845,7 +855,13 @@ The following extra functions are defined:
- `godoc'
- `go-import-add'
- `go-remove-unused-imports'
+- `go-goto-arguments'
+- `go-goto-docstring'
+- `go-goto-function'
+- `go-goto-function-name'
- `go-goto-imports'
+- `go-goto-return-values'
+- `go-goto-method-receiver'
- `go-play-buffer' and `go-play-region'
- `go-download-play'
- `godef-describe' and `godef-jump'
@@ -1562,6 +1578,236 @@ for."
(if (not (eq cur-buffer (current-buffer)))
(display-buffer (current-buffer)
`(,go-coverage-display-buffer-func))))))
+(defun go-goto-function (&optional arg)
+ "Go to the function defintion (named or anonymous) surrounding point.
+
+If we are on a docstring, follow the docstring down.
+If no function is found, assume that we are at the top of a file
+and search forward instead.
+
+If point is looking at the func keyword of an anonymous function,
+go to the surrounding function.
+
+If ARG is non-nil, anonymous functions are ignored."
+ (interactive "P")
+ (let ((p (point)))
+ (cond
+ ((save-excursion
+ (beginning-of-line)
+ (looking-at "^//"))
+ ;; In case we are looking at the docstring, move on forward until we are
+ ;; not anymore
+ (beginning-of-line)
+ (while (looking-at "^//")
+ (forward-line 1))
+ ;; If we are still not looking at a function, retry by calling self
again.
+ (when (not (looking-at "\\<func\\>"))
+ (go-goto-function arg)))
+
+ ;; If we're already looking at an anonymous func, look for the
+ ;; surrounding function.
+ ((and (looking-at "\\<func\\>")
+ (not (looking-at "^func\\>")))
+ (re-search-backward "\\<func\\>" nil t))
+
+ ((not (looking-at "\\<func\\>"))
+ ;; If point is on the "func" keyword, step back a word and retry
+ (if (string= (symbol-name (symbol-at-point)) "func")
+ (backward-word)
+ ;; If we are not looking at the beginning of a function line, do a
regexp
+ ;; search backwards
+ (re-search-backward "\\<func\\>" nil t))
+
+ ;; If nothing is found, assume that we are at the top of the file and
+ ;; should search forward instead.
+ (when (not (looking-at "\\<func\\>"))
+ (re-search-forward "\\<func\\>" nil t)
+ (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
+ ;; go to the containing function.
+ (while (and (not (go--in-function-p p))
+ (not (looking-at "^func\\>")))
+ (go-goto-function arg)))))
+
+ (cond
+ ((go-in-comment-p)
+ ;; If we are still in a comment, redo the call so that we get out of it.
+ (go-goto-function arg))
+
+ ((and (looking-at "\\<func(") arg)
+ ;; If we are looking at an anonymous function and a prefix argument has
+ ;; been supplied, redo the call so that we skip the anonymous function.
+ (go-goto-function arg))))
+
+(defun go--goto-opening-curly-brace ()
+ ;; Find the { that starts the function, i.e., the next { that isn't
+ ;; preceded by struct or interface, or a comment or struct tag. BUG:
+ ;; breaks if there's a comment between the struct/interface keyword and
+ ;; bracket, like this:
+ ;;
+ ;; struct /* why? */ {
+ (go--goto-return-values)
+ (while (progn
+ (skip-chars-forward "^{")
+ (forward-char)
+ (or (go-in-string-or-comment-p)
+ (looking-back "\\(struct\\|interface\\)\\s-*{"))))
+ (backward-char))
+
+(defun go--in-function-p (compare-point)
+ "Return t if COMPARE-POINT lies inside the function immediately surrounding
point."
+ (save-excursion
+ (when (not (looking-at "\\<func\\>"))
+ (go-goto-function))
+ (let ((start (point)))
+ (go--goto-opening-curly-brace)
+
+ (unless (looking-at "{")
+ (error "expected to be looking at opening curly brace"))
+ (forward-list 1)
+ (and (>= compare-point start)
+ (<= compare-point (point))))))
+
+(defun go-goto-function-name (&optional arg)
+ "Go to the name of the current function.
+
+If the function is a test, place point after 'Test'.
+If the function is anonymous, place point on the 'func' keyword.
+
+If ARG is non-nil, anonymous functions are skipped."
+ (interactive "P")
+ (when (not (looking-at "\\<func\\>"))
+ (go-goto-function arg))
+ ;; If we are looking at func( we are on an anonymous function and
+ ;; nothing else should be done.
+ (when (not (looking-at "\\<func("))
+ (let ((words 1)
+ (chars 1))
+ (when (looking-at "\\<func (")
+ (setq words 3
+ chars 2))
+ (forward-word words)
+ (forward-char chars)
+ (when (looking-at "Test")
+ (forward-char 4)))))
+
+(defun go-goto-arguments (&optional arg)
+ "Go to the arguments of the current function.
+
+If ARG is non-nil, anonymous functions are skipped."
+ (interactive "P")
+ (go-goto-function-name arg)
+ (forward-word 1)
+ (forward-char 1))
+
+(defun go--goto-return-values (&optional arg)
+ "Go to the declaration of return values for the current function."
+ (go-goto-arguments arg)
+ (backward-char)
+ (forward-list)
+ (forward-char))
+
+(defun go-goto-return-values (&optional arg)
+ "Go to the return value declaration of the current function.
+
+If there are multiple ones contained in a parenthesis, enter the parenthesis.
+If there is none, make space for one to be added.
+
+If ARG is non-nil, anonymous functions are skipped."
+ (interactive "P")
+ (go--goto-return-values arg)
+
+ ;; Opening parenthesis, enter it
+ (when (looking-at "(")
+ (forward-char 1))
+
+ ;; No return arguments, add space for adding
+ (when (looking-at "{")
+ (insert " ")
+ (backward-char 1)))
+
+(defun go-goto-method-receiver (&optional arg)
+ "Go to the receiver of the current method.
+
+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,
+an error is raised unless ARG is non-nil."
+ (interactive "P")
+
+ (when (and (not (called-interactively-p 'interactive))
+ (not arg)
+ (go--in-anonymous-funcion-p))
+ (error "Anonymous functions cannot have method receivers"))
+
+ (go-goto-function t) ; Always skip anonymous functions
+ (forward-char 5)
+ (when (not (looking-at "("))
+ (save-excursion
+ (insert "() ")))
+ (forward-char 1))
+
+(defun go-goto-docstring (&optional arg)
+ "Go to the top of the docstring of the current function.
+
+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,
+an error is raised unless ARG is non-nil."
+ (interactive "P")
+
+ (when (and (not (called-interactively-p 'interactive))
+ (not arg)
+ (go--in-anonymous-funcion-p))
+ (error "Anonymous functions do not have docstrings"))
+
+ (go-goto-function t)
+ (forward-line -1)
+ (beginning-of-line)
+
+ (while (looking-at "^//")
+ (forward-line -1))
+ (forward-line 1)
+ (beginning-of-line)
+
+ (cond
+ ;; If we are looking at an empty comment, add a single space in front of it.
+ ((looking-at "^//$")
+ (forward-char 2)
+ (insert (format " %s " (go--function-name t))))
+ ;; If we are not looking at the function signature, we are looking at a
docstring.
+ ;; Move to the beginning of the first word of it.
+ ((not (looking-at "^func"))
+ (forward-char 3))
+ ;; If we are still at the function signature, we should add a new docstring.
+ (t
+ (forward-line -1)
+ (newline)
+ (insert (format "// %s " (go--function-name t))))))
+
+(defun go--function-name (&optional arg)
+ "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
+nil and the surrounding function is anonymous, nil will be
+returned."
+ (when (or (not (go--in-anonymous-funcion-p))
+ arg)
+ (save-excursion
+ (go-goto-function-name t)
+ (symbol-name (symbol-at-point)))))
+
+(defun go--in-anonymous-funcion-p ()
+ "Return t if point is inside an anonymous function, nil otherwise."
+ (save-excursion
+ (go-goto-function)
+ (looking-at "\\<func(")))
+
(provide 'go-mode)
;;; go-mode.el ends here
- [nongnu] elpa/go-mode dce210f 250/495: Bump version to 1.3.1, (continued)
- [nongnu] elpa/go-mode dce210f 250/495: Bump version to 1.3.1, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 8baa836 251/495: Don't break fontification when limiting point, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode dccb56c 256/495: go-unused-imports-lines: only compile the current file, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d91a157 257/495: Add goto functions for working with function signatures, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 11e7b4e 259/495: Fix copy-pasted docstring of go-goto-arguments, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode b261fac 263/495: Add support for (nested) anonymous functions in go-goto-function, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 6e8373e 267/495: go-goto-docstring: handle empty comments, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d1ebde8 271/495: Rename go--get-function-name to go--function-name, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode eddbcff 277/495: Make sure we're looking at func keyword, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 45a8131 284/495: Implement go--goto-opening-curly-brace as in go-end-of-defun, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d6aa01a 287/495: Merge branch 'movement',
ELPA Syncer <=
- [nongnu] elpa/go-mode 27b7415 293/495: Allow passing additional arguments to gofmt, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 1214f77 294/495: Bind go-goto-map to C-f, not C-g, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 17bd2b2 296/495: Add GOPATH detection, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 9f785cc 298/495: Document stability of the master branch, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode f8b4bf9 300/495: Add to beginning of compilation-error-regexp-alist, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode cfaa193 348/495: cmd/guru: rename oracle to guru, copying it to a single package, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 4d1ab9f 347/495: cmd/oracle: improve error messages, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 9c2bf9b 360/495: cmd/guru: emacs: push mark in go-guru-definition, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 5ef1d53 355/495: cmd/guru: use byte (not rune) count in -modified archive, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 60ed26e 368/495: cmd/guru: emacs: only check modified buffers with file names, ELPA Syncer, 2021/08/07