unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Evgeni Kolev <evgenysw@gmail.com>
To: 61368@debbugs.gnu.org
Cc: Randy Taylor <dev@rjt.dev>, Theodor Thornhill <theo@thornhill.no>
Subject: bug#61368: [PATCH] Extend go-ts-mode with support for pre-filling return statements
Date: Wed, 8 Feb 2023 17:27:58 +0200	[thread overview]
Message-ID: <CAMCrgaUgMx9+0Q8f_cezZ0TW_-u=mdeHf=TL=qw9wbhiS-nJ9w@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2804 bytes --]

[CC Randy, author of go-ts-mode, Theo, who asked to keep the patches coming :)]

This is a patch which adds support to go-ts-mode to insert
context-aware return statements for the current function. The return
statements are pre-filled with the Go zero values of the output
parameters.

For example, all these return statements are inserted by M-x
go-ts-mode-insert-return:

```
func f() (x, y, z int) {
    return 0, 0, 0
}

func exotic() (bool, int, myStruct, *int, chan bool, error) {
    return false, 0, myStruct{}, nil, nil, err
}

func closure(numbers []int) {
    sort.Slice(numbers, func(i, j int) bool {
        return false
    })
}
```

The command go-ts-mode-insert-return is experimentally bound to a key
C-c C-r ("r" as return statement). It's a user error to run C-c C-r
outside of a function body.

Customization: when the output params contain "error" the pre-filled
text is "err". A customization variable is added to allow the user to
pick a different value, for example they might pick `fmt.Errorf("...:
%w", err)` which will result in error wrapping:
```
func f() (int, error) {
    return 0, fmt.Errorf("...: %w", err)
}
```

Personally, I'll use yasnippet instead of C-c C-r. Something like this:
```
 # -*- mode: snippet -*-
 # name: ret
 # key: ret
 # type: command
 # --

 (let ((go-ts-mode-error-zero-value "${1:fmt.Errorf(\"${2:format}:
%w\", err)}"))
   (yas-expand-snippet (go-ts-mode-return)))
```

I'm open to suggestions about how to best expose this functionality to
the user. I think a snippet makes the most sense, but there's no
standard way for major modes to expose snippets as far as I'm aware.
It's possible to tweak C-c C-r to call (yas-expand-snippet) if
available, otherwise call (insert). In general, I don't feel strong
about the C-c C-r key binding, but I didn't have a better idea.

Known bug: this example does not work, fails with error "Unknown Go
type "[int]int"":
```
func notOk() (int, map[int]int) {
}
```
The root cause is an issue with the tree-sitter-go parser. The bug has
been reported here
https://github.com/tree-sitter/tree-sitter-go/issues/107

Known limitation: unfamiliar types are assumed to be structs. This
assumption does not work for aliased types. For example:
```
type MyInt = int

func alias() MyInt {
    return MyInt{}
}
```
Above the correct return statement is "return MyInt(0)". My assumption
is that type aliases of primitive types are rare in Go codebases. In
these rare cases, the user is expected to replace "MyInt{}" with
"MyInt(0)", or not use C-c C-r at all.

Inspired by: this emacs conf talk "08:21 Intelligent templates"
https://emacsconf.org/2022/talks/treesitter/

Feedback is more than welcome! In particular:
- how to best expose the functionality - key binding, snippet (how
exactly?), something else?

Evgeni

[-- Attachment #2: 0001-Extend-go-ts-mode-with-support-for-pre-filling-retur.patch --]
[-- Type: application/x-patch, Size: 6378 bytes --]

             reply	other threads:[~2023-02-08 15:27 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-08 15:27 Evgeni Kolev [this message]
2023-02-08 16:30 ` bug#61368: [PATCH] Extend go-ts-mode with support for pre-filling return statements Eli Zaretskii
2023-02-09 11:47   ` Evgeni Kolev
2023-02-09 13:39     ` Eli Zaretskii
2023-02-18 11:46       ` Evgeni Kolev
2023-02-18 12:14         ` João Távora
2023-02-20  8:54           ` Evgeni Kolev
2023-02-20 12:55             ` Eli Zaretskii
2023-02-22 14:36               ` Evgeni Kolev
2024-01-10 22:43                 ` Stefan Kangas
2024-01-15  8:21                   ` Evgeni Kolev
2024-01-15  8:39                     ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-15 11:40                       ` João Távora
2023-02-08 19:20 ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAMCrgaUgMx9+0Q8f_cezZ0TW_-u=mdeHf=TL=qw9wbhiS-nJ9w@mail.gmail.com' \
    --to=evgenysw@gmail.com \
    --cc=61368@debbugs.gnu.org \
    --cc=dev@rjt.dev \
    --cc=theo@thornhill.no \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).