1

Golang uses naming convention to separate functions visibility: exported (public) starts with a capital letter, non-exported (private) with a lower letter. I would like to highlight exported functions, so it would be easier to explore new files and APIs. Here is my try:

match Title /func [A-Z][a-z0-9_]*/

Is there a way to improve it somehow? For example, right now func is highlighted with the name. Is it possible to get rid of it? Maybe someone have better proposals for regex? Also, how to apply this only for Go?

  • 4
    try: match Title /func \zs[A-Z][a-z0-9_]*/ – Christian Brabandt Oct 25 '17 at 10:23
  • @ChristianBrabandt, yep that did the trick, only the function name is highlighted. – grundic Oct 25 '17 at 11:05
  • 1
    CamelCase names seem to be allowed in Go, so wouldn't the correct regular expression be /func [A-Z][A-Za-z0-9_]*? This can then be written more concisely as /func \u\w*/ – Rich Oct 27 '17 at 14:29
4

To borrow @Christian Brabandt's answer in the comments (and break it down further):

match Title /func \zs[A-Z][a-z0-9_]*/

The regex is the same as before, but the \zs marker effectively tells Vim, "Here's where the match starts." So we can use this to find the word func, followed by a space, followed by a valid public Go function name, but we only match from the beginning of the function name.

To add this to only Go files, you have two options.

Filetype plugins (preferred)

Drop this in ~/.vim/syntax/go.vim to overrule go highlighting, or ~/.vim/after/syntax/go.vim to modify go highlighting:

match Title /func \zs[A-Z][a-z0-9_]*/

Autocommands

Drop this in your .vimrc

augroup GoFuncHighlight
  au!
  au FileType go match Title /func \zs[A-Z][a-z0-9_]*/
augroup END

This way, when a filetype is set to "go", we get the match command run

Further Reading

  • :help autocmd
  • :help FileType
  • :help filetype
  • :help syntax
  • :help \zs

As @Carpetsmoker states in the comments:

Note that this won’t work for (exported) receiver methods, which look like func (f Type) Name(). In addition unicode identifiers are allowed in Go [...].

  • I know grundic used :match in their question, but it makes sense to use a :syntax command for this, doesn't it? Especially in the case where you're putting it in a syntax file. – Rich Oct 27 '17 at 8:55
  • @Rich syntax commands aren’t my strong suit off the top of my head, but I’d be happy to update my answer later with an alternate method using syntax commands. – D. Ben Knoble Oct 27 '17 at 12:05
  • 1
    It turned out to be slightly more complicated than I was expecting. I wrote my own answer – Rich Oct 27 '17 at 14:25
  • Note that this won't work for (exported) receiver methods, which look like func (f Type) Name(). In addition unicode identifiers are allowed in Go; func ЛЛЛ() is a perfectly valid (exported) function name. – Martin Tournoij Nov 29 '17 at 2:18
  • 1
    Yeah, that's understandable. Just wanted to point out the caveats/limitations for future readers :-) – Martin Tournoij Nov 29 '17 at 3:23
3

David Ben Knoble has already given you a good, working solution.

However, seeing as this is syntax that you're highlighting, I feel like it's cleaner to perform the task with a :syntax command. This also has the slight advantage that :match is free for other purposes.

For reasons I'm slightly unclear on, it's not possible to use the previously explained \zs atom in this match, but it's easy to achieve using a syntax pattern offset instead. Drop the following command in the file ~/.vim/after/syntax/go.vim:

syntax match goExportedFunction /func [A-Z][a-z0-9_]*/hs=s+5 contains=goDeclaration
highlight default link goExportedFunction Title

This syntax group will take precedence over the existing goDeclaration group used for the func because it starts in the same position, but was declared later.

The hs=s+5 after the regular expression tells Vim that you want the highlighting to start 5 characters after the beginning of the match i.e. at the start of the function name.

The contains=goDeclaration might not strictly be necessary depending on your colour scheme, but it means that the func at the beginning of the line is still matched by the goDeclaration group in the same way as before.

N.B. For clarity, I've used the same basic regular expression as you used. However, as I suggested in a comment, the following is faster, more concise, and more correct:

syntax match goExportedFunction /func \u\w*/hs=s+5 contains=goDeclaration

Further Reading

  • :help :syn-priority
  • :help :syn-pattern-offset
  • :help :syn-contains
  • Very nice! Would it be a good idea to integrate to the default go.vim syntax? – grundic Oct 27 '17 at 14:36
  • Seems like it would be! But I don't know Go well enough (read: at all) to say definitively that that's the case. – Rich Oct 27 '17 at 14:39
  • 1
    @DavidBenKnoble Whoops! Good catch. I've edited my answer to do this, as it should. – Rich Oct 27 '17 at 16:11
  • 1
    Note that this won't work for (exported) receiver methods, which look like func (f Type) Name(). In addition unicode identifiers are allowed in Go; func ЛЛЛ() is a perfectly valid (exported) function name. – Martin Tournoij Nov 29 '17 at 2:17
  • 1
    As a vim-go maintainer, I'm not sure about integrating it in vim-go @grundic; I actually took a quick look at this earlier, and it requires some work with contained syntax groups and such, and there are already a whole bunch of knobs/settings which makes it all rather complex. Personally I think this feature is a bit too specific/obscure for adding there, and adding it in your own vimrc file is easy enough. – Martin Tournoij Nov 29 '17 at 3:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.