branch: elpa/go-mode
commit d91a1578b59f849f6c1bcdeb8ab972dac0bb3410
Author: Lowe Thiderman <[email protected]>
Commit: Lowe Thiderman <[email protected]>
Add goto functions for working with function signatures
Add several functions:
- `go-goto-arguments`
- `go-goto-docstring`
- `go-goto-function`
- `go-goto-function-name`
- `go-goto-return-value`
- `go-goto-type-signature`
They are all about going to different parts of function signatures, with
their names being self descriptive. They all operate on the current
function, the definition of which is "the closest `func` statement above
point". If no `func` is found above point, the functions will jump to
the first `func` in the file. Lastly, if the point is in the docstring
of a function, the goto functions will operate on that function and not
the function above.
Additionally, some of the functions will create their targets if they are
missing:
- `go-goto-docstring` will create a docstring if it does not
exist as well as update the docstring name for a function that has been
renamed.
- `go-goto-return-value` will add space for adding return values.
- `go-goto-type-signature` will add spaces and a pair of parenthesis for
adding a signature.
It should also be noted that the functions have been tested with
anonymous functions as well.
Add keymap at `C-c C-g` for goto functions.
Add mapping for the already existing `go-goto-imports` at `C-c C-g i`.
Add helper function `go--get-function-name`, which grabs the string of
the function above point.
Update README to reflect the addition of these functions.
---
README.md | 12 +++++-
go-mode.el | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 6e5a780..8143036 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,15 @@ 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 goto functions for manipulating function signatures:
+ - Going to the arguments (`go-goto-arguments` - `C-c C-g a`)
+ - Going to the docstring, creating it if it does not exist and updating it
+ if the name does not match (`go-goto-docstring` - `C-c C-g d`)
+ - Going to the function name (`go-goto-function-name` - `C-c C-g f`)
+ - Going to the return value, adding space for adding one if there are none
+ present (`go-goto-return-value` - `C-c C-g r`)
+ - Going to the type signature, adding parenthesis for adding one if there is
+ none present (`go-goto-type-signature` - `C-c C-g t`)
# Installation
diff --git a/go-mode.el b/go-mode.el
index 851b937..4ae3c40 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -845,7 +845,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-value'
+- `go-goto-type-signature'
- `go-play-buffer' and `go-play-region'
- `go-download-play'
- `godef-describe' and `godef-jump'
@@ -1562,6 +1568,129 @@ for."
(if (not (eq cur-buffer (current-buffer)))
(display-buffer (current-buffer)
`(,go-coverage-display-buffer-func))))))
+(define-prefix-command 'go-goto-map)
+(define-key go-mode-map (kbd "C-c C-g") 'go-goto-map)
+
+(defun go-goto-function ()
+ "Go to the function defintion above 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."
+ (interactive)
+
+ (beginning-of-line)
+ (cond
+ ((looking-at "^//")
+ ;; In case we are looking at the docstring, move on forward until we are
not anymore
+ (while (looking-at "^//")
+ (forward-line 1)))
+ ((not (looking-at "^func"))
+ ;; If we are not looking at the beginning of a function line, do a regexp
search backwards
+ (re-search-backward "\\<func\\>" nil t)
+
+ (when (not (looking-at "func"))
+ (re-search-forward "\\<func\\>" nil t)
+ (backward-word)))))
+
+(defun go-goto-function-name ()
+ "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."
+ (interactive)
+ (when (not (looking-at "func"))
+ (go-goto-function))
+ ;; 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)))))
+
+(define-key go-goto-map (kbd "f") 'go-goto-function-name)
+
+(defun go-goto-arguments ()
+ "Go to the return value declaration of the current function."
+ (interactive)
+ (go-goto-function-name)
+ (forward-word 1)
+ (forward-char 1))
+
+(define-key go-goto-map (kbd "a") 'go-goto-arguments)
+
+(defun go-goto-return-value ()
+ "Go to the return value declaration of the current function.
+
+If there is none, make space for one to be added."
+ (interactive)
+ (go-goto-arguments)
+ (re-search-forward ")" nil t)
+ (forward-char 1)
+
+ ;; Opening parenthesis, enter it
+ (when (looking-at "(")
+ (forward-char 1))
+ ;; First item is a pointer, move past the pointer
+ (when (looking-at "*")
+ (forward-char 1))
+ ;; No return arguments, add space for adding
+ (when (looking-at "{")
+ (insert " ")
+ (backward-char 1)))
+
+(define-key go-goto-map (kbd "r") 'go-goto-return-value)
+
+;; Since this is already defined, just add the key to it.
+(define-key go-goto-map (kbd "i") 'go-goto-imports)
+
+(defun go-goto-type-signature ()
+ "Go to the type signature of the current function.
+
+If there is none, add parenthesis to add one."
+ (interactive)
+ (go-goto-function)
+ (forward-char 5)
+ (when (not (looking-at "("))
+ (save-excursion
+ (insert "() ")))
+ (forward-char 1))
+
+(define-key go-goto-map (kbd "t") 'go-goto-type-signature)
+
+(defun go-goto-docstring ()
+ "Go to the top of the docstring of the current function.
+
+If there is none, add one."
+ (interactive)
+ (go-goto-function)
+ (forward-line -1)
+ (beginning-of-line)
+ (while (looking-at "^//")
+ (forward-line -1))
+ (next-line 1)
+ (beginning-of-line)
+ (if (not (looking-at "^func"))
+ (forward-char 3)
+ ;; If we are still at the function signature, we should add a new
docstring.
+ (forward-line -1)
+ (newline)
+ (insert (format "// %s " (go--get-function-name)))))
+
+(define-key go-goto-map (kbd "d") 'go-goto-docstring)
+
+(defun go--get-function-name ()
+ "Return the current function name as a string"
+ (save-excursion
+ (go-goto-function-name)
+ (symbol-name (symbol-at-point))))
+
(provide 'go-mode)
;;; go-mode.el ends here