├── extension.png
├── extension@2x.png
├── .prettierrc.json
├── Images
└── extension
│ └── Go-Nova-Banner.png
├── .gitignore
├── Tests
├── go.mod.sample
└── basictest.go
├── LICENSE.md
├── .all-contributorsrc
├── extension.json
├── Syntaxes
├── Go-Template.xml
├── Go-Mod.xml
└── Go.xml
├── Scripts
├── lsp.js
└── main.js
├── Completions
└── Go.xml
├── CHANGELOG.md
└── README.md
/extension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GwynethLlewelyn/Go.novaextension/HEAD/extension.png
--------------------------------------------------------------------------------
/extension@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GwynethLlewelyn/Go.novaextension/HEAD/extension@2x.png
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": true,
5 | "singleQuote": true
6 | }
--------------------------------------------------------------------------------
/Images/extension/Go-Nova-Banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GwynethLlewelyn/Go.novaextension/HEAD/Images/extension/Go-Nova-Banner.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Stupid macOS temporary files
2 |
3 | # General
4 | .DS_Store
5 | .AppleDouble
6 | .LSOverride
7 |
8 | # Icon must end with two \r
9 | Icon
10 |
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear in the root of a volume
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 | .com.apple.timemachine.donotpresent
23 |
24 | # Directories potentially created on remote AFP share
25 | .AppleDB
26 | .AppleDesktop
27 | Network Trash Folder
28 | Temporary Items
29 | .apdisk
30 |
31 | # Stuff from the Nova editor
32 | .nova
33 |
--------------------------------------------------------------------------------
/Tests/go.mod.sample:
--------------------------------------------------------------------------------
1 | module golang.org/x/net
2 |
3 | go 1.11
4 |
5 | require (
6 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
7 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
8 | golang.org/x/text v0.3.3
9 | )
10 |
11 | replace (
12 | github.com/etcd-io/bbolt => go.etcd.io/bbolt v1.3.5
13 | github.com/mholt/caddy => github.com/caddyserver/caddy v1.0.5
14 | github.com/nats-io/go-nats => github.com/nats-io/nats.go v1.8.1
15 | github.com/nats-io/go-nats-streaming => github.com/nats-io/stan.go v0.5.0
16 | github.com/nats-io/nats => github.com/nats-io/nats.go v1.8.0
17 | go.uber.org/atomic => github.com/uber-go/atomic v1.5.0
18 | )
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2020-2021 Gwyneth Llewelyn, John Fieber, Daniel Seripap
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 | Parts of the code may be subject to the [Microsoft Public License (MS-PL)](https://opensource.org/licenses/MS-PL)
--------------------------------------------------------------------------------
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "seripap",
10 | "name": "Daniel Seripap",
11 | "avatar_url": "https://avatars.githubusercontent.com/u/683200?v=4",
12 | "profile": "http://daniel.seripap.com",
13 | "contributions": [
14 | "code"
15 | ]
16 | },
17 | {
18 | "login": "tooolbox",
19 | "name": "Matt Mc",
20 | "avatar_url": "https://avatars.githubusercontent.com/u/4984708?v=4",
21 | "profile": "https://github.com/tooolbox",
22 | "contributions": [
23 | "ideas",
24 | "question"
25 | ]
26 | },
27 | {
28 | "login": "jfieber",
29 | "name": "John Fieber",
30 | "avatar_url": "https://avatars.githubusercontent.com/u/113956?v=4",
31 | "profile": "https://github.com/jfieber",
32 | "contributions": [
33 | "code",
34 | "ideas",
35 | "doc"
36 | ]
37 | },
38 | {
39 | "login": "apexskier",
40 | "name": "Cameron Little",
41 | "avatar_url": "https://avatars.githubusercontent.com/u/329222?v=4",
42 | "profile": "https://camlittle.com",
43 | "contributions": [
44 | "ideas"
45 | ]
46 | }
47 | ],
48 | "contributorsPerLine": 7,
49 | "projectName": "Go.novaextension",
50 | "projectOwner": "GwynethLlewelyn",
51 | "repoType": "github",
52 | "repoHost": "https://github.com",
53 | "skipCi": true
54 | }
55 |
--------------------------------------------------------------------------------
/Tests/basictest.go:
--------------------------------------------------------------------------------
1 | // Testing formatting/imports
2 | package main
3 |
4 | import (
5 | _ "errors"
6 | "os"
7 | "fmt"
8 | myPtr "golang.org/x/net/html/atom" // hnmrs"
9 | )
10 |
11 | // foo bar cat.
12 | func foo(s string) string {
13 | return s
14 | }
15 |
16 | type User struct {
17 | FirstName string
18 | LastName string
19 | Age int
20 | Admin bool
21 | }
22 |
23 | // myFunc does something not very useful.
24 | func myFunc(a string, b string) bool {
25 | return a != b // no? why the weird error?
26 | }
27 |
28 | // anotherFunc serves no purpose whatsoever.
29 | func anotherFunc(a, b string) string {
30 | return a + b
31 | }
32 |
33 | // Greeting is a list of methods.
34 | func (u *User) Greeting(what string, users User) string {
35 | var blip myPtr.Atom
36 | return fmt.Sprintf("Dear %s %s %v: %s", u.FirstName, u.LastName, blip, what)
37 | }
38 |
39 | /*
40 | Hey, this is a comment.
41 | */
42 | // TODO(gwyneth): Change everything!
43 | func main() {
44 | // huh
45 | // add a comment here
46 | // and another
47 | /* inclie */
48 | /// There were some issues with 3 slashes at the beginning
49 |
50 | // var a = 'w'
51 | var a []byte
52 | var v = 1
53 | t := make([]byte, 1, 2)
54 | b := append(t, a[0], byte(1), 0.00, byte(0x08))
55 | complexNumber := -4.0436 + 3.76e-5i // almost correctly formatted/captured by the regex
56 | exponential := -3.167252381e-12
57 | hex := 0x0f - 0x0f0f
58 | octal := 0777
59 | v = octal + hex
60 |
61 | var (
62 | google []byte
63 | x string
64 | c int64
65 | )
66 | Main := "var"
67 | heredoc := `hi`
68 | fmt.Println("nothing works...", heredoc) // was
69 | fmt.Println("Clearly nothing yet...", google, x, c, t, b, v, complexNumber, exponential, octal)
70 | fmt.Println("wth?...")
71 | println("something")
72 | fmt.Printf("%s%v\n", Main, hex)
73 |
74 | var user User //
75 |
76 | pointer := &user
77 |
78 | i := 1
79 |
80 | var err error
81 |
82 | if i > 0 && err != nil {
83 | // do something
84 | pointer.Greeting(os.TempDir(), *pointer)
85 | } else {
86 | // do something else somewhere
87 | fmt.Println("Something else")
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/extension.json:
--------------------------------------------------------------------------------
1 | {
2 | "identifier": "gwynethllewelyn.Go",
3 | "name": "Go",
4 | "organization": "Gwyneth Llewelyn",
5 | "description": "Go Language Definition for Nova",
6 | "version": "0.4.3",
7 | "min_runtime": "6.0",
8 | "bugs": "https://github.com/GwynethLlewelyn/Go.novaextension/issues",
9 | "repository": "https://github.com/GwynethLlewelyn/Go.novaextension",
10 | "homepage": "https://gwynethllewelyn.net",
11 | "funding": "https://www.paypal.com/paypalme/gwynethllewelyn",
12 | "keywords": ["go", "golang"],
13 | "license": "MIT",
14 | "categories": ["completions", "languages"],
15 | "main": "main.js",
16 | "activationEvents": ["onLanguage:Go", "onWorkspaceContains:*.go"],
17 | "entitlements": {
18 | "process": true,
19 | "requests": false,
20 | "filesystem": "readwrite"
21 | },
22 | "config": [
23 | {
24 | "key": "go-nova.enable-gopls",
25 | "title": "Enable Language Server",
26 | "description": "Use the `gopls` language server for enhanced functionality. The `gopls` command should be installed in your search path, or you can specify the full path below.",
27 | "link": "https://github.com/golang/tools/blob/master/gopls/README.md",
28 | "type": "boolean",
29 | "default": false
30 | },
31 | {
32 | "key": "go-nova.gopls-path",
33 | "title": "Language Server Command",
34 | "link": "https://github.com/golang/tools/blob/master/gopls/README.md",
35 | "description": "The command name to start the `gopls` language server. Use an absolute path here if `gopls` is not in your search path ($PATH environment variable).",
36 | "type": "path",
37 | "default": "gopls",
38 | "filetype": ["public.unix-executable"]
39 | },
40 | {
41 | "key": "go-nova.format-on-save",
42 | "title": "(Experimental) Format/Organize Imports when saving file (DANGEROUS!)",
43 | "description": "When saving, use `gopls` to format file according to Go formatting standards and organize imports (the equivalent of executing `gofmt`, `goimports`, `goreturns`). Requires `gopls` language server to be active.\nWARNING: For experimental purposes ONLY! Currently it WILL DESTROY YOUR FILES!",
44 | "type": "boolean",
45 | "default": false
46 | },
47 | {
48 | "key": "go-nova.use-staticcheck",
49 | "title": "(Experimental) Use https://staticcheck.io for further analysis",
50 | "description": "Use `gopls` in conjunction with https://staticcheck.io for further analysis of the code. This also requires `gopls` language server to be active.",
51 | "type": "boolean",
52 | "default": false
53 | }
54 | ],
55 | "commands": {
56 | "editor": [
57 | {
58 | "title": "Jump to Definition",
59 | "command": "go.jumpToDefinition",
60 | "when": "editorHasFocus",
61 | "filters": {
62 | "syntaxes": ["go"]
63 | }
64 | },
65 | {
66 | "title": "Organize Imports",
67 | "command": "go.organizeImports",
68 | "when": "editorHasFocus",
69 | "filters": {
70 | "syntaxes": ["go"]
71 | }
72 | },
73 | {
74 | "title": "Format File",
75 | "command": "go.formatFile",
76 | "when": "editorHasFocus",
77 | "filters": {
78 | "syntaxes": ["go"]
79 | }
80 | }
81 | ]
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Syntaxes/Go-Template.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Go templates
5 | markup
6 | tpl
7 | html
8 |
9 |
10 |
11 | tpl
12 |
13 |
14 |
15 |
16 | $
17 |
18 |
19 |
20 |
21 |
22 | <(?!(?i:\!DOCTYPE|area|base|basefront|br|col|embed|frame|hr|img|input|keygen|link|meta|object|param|source)|[^>]*/>)([A-Za-z0-9]+)(?=\s|>)[^>]*>(?!.*</\1>)
23 |
24 |
25 | [\s]*</([A-Za-z0-9]+)(?=\s|>)[^>]*>
26 |
27 |
28 |
29 |
30 |
31 |
32 | <!--
33 |
34 |
35 | -->
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | \{\{
65 |
66 |
67 |
68 | \}\}
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | (\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
83 |
84 |
85 |
86 |
87 | (\.[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/Syntaxes/Go-Mod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Go Modules List
5 | structured
6 | mod
7 |
8 |
9 |
10 |
11 | go.mod
12 |
13 |
14 |
15 |
16 | (\([^)\"']*$)
17 |
18 |
19 | ^\s*(\s*/\*.*\*/\s*)*[\)\\]
20 |
21 |
22 |
23 |
24 |
25 | //
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | (module)\s*([a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9_\.\/]+)
43 |
44 |
45 |
46 |
47 |
48 |
49 | (go)\s*([0-9]*\.?[0-9]+\.?[0-9]*)
50 |
51 |
52 |
53 |
54 |
55 |
56 | \/\/.*$
57 |
58 |
59 |
60 |
61 |
62 | (require)\s*(\()
63 |
64 |
65 |
66 |
67 | (\))
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | (replace)\s*(\()
79 |
80 |
81 |
82 |
83 | (\))
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | true
100 | false
101 |
102 |
103 |
104 |
105 | \b(\-|\+)?(?:\d+(?:\.\d*)?|(?:\.\d+))\b
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | "(?:[^"\\]|\\.)*(?:"|$)
114 |
115 |
116 | '(?:[^'\\]|\\.)*(?:'|$)
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | module
126 | go
127 | require
128 | replace
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | =>
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | [a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9\-_\.\/]+
147 |
148 |
149 |
150 |
151 |
152 |
153 | \s*([a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9\-_\.\/]+)\s*(\S*).*$
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | ^\s*([a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9\-_\.\/]+)\s(\=\>)\s*([a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9\-_\.\/]+)\s*([\w\.\-]*).*$
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/Scripts/lsp.js:
--------------------------------------------------------------------------------
1 | // Turn a Nova start-end range to an LSP row-column range.
2 | // From https://github.com/apexskier/nova-typescript
3 | //
4 | // Adding the original license terms from Microsoft, as shown on @apexskier's
5 | // own files (gwyneth 20200130)
6 | // Probably this is the [Microsoft Public License (MS-PL)](https://opensource.org/licenses/MS-PL)
7 | //
8 | /*! *****************************************************************************
9 | Copyright (c) Microsoft Corporation.
10 |
11 | Permission to use, copy, modify, and/or distribute this software for any
12 | purpose with or without fee is hereby granted.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
15 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 | PERFORMANCE OF THIS SOFTWARE.
21 | ***************************************************************************** */
22 | //
23 | exports.RangeToLspRange = function (document, range) {
24 | const fullContents = document.getTextInRange(new Range(0, document.length));
25 | let chars = 0;
26 | let startLspRange;
27 | const lines = fullContents.split(document.eol);
28 | for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
29 | const lineLength = lines[lineIndex].length + document.eol.length;
30 | if (!startLspRange && chars + lineLength >= range.start) {
31 | const character = range.start - chars;
32 | startLspRange = { line: lineIndex, character };
33 | }
34 | if (startLspRange && chars + lineLength >= range.end) {
35 | const character = range.end - chars;
36 | return {
37 | start: startLspRange,
38 | end: { line: lineIndex, character },
39 | };
40 | }
41 | chars += lineLength;
42 | }
43 | return null;
44 | };
45 |
46 | // Turn an LSP row-column range to a Nova start-end range.
47 | // From https://github.com/apexskier/nova-typescript
48 | exports.LspRangeToRange = function (document, range) {
49 | const fullContents = document.getTextInRange(new Range(0, document.length));
50 | let rangeStart = 0;
51 | let rangeEnd = 0;
52 | let chars = 0;
53 | const lines = fullContents.split(document.eol);
54 | for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
55 | const lineLength = lines[lineIndex].length + document.eol.length;
56 | if (range.start.line === lineIndex) {
57 | rangeStart = chars + range.start.character;
58 | }
59 | if (range.end.line === lineIndex) {
60 | rangeEnd = chars + range.end.character;
61 | break;
62 | }
63 | chars += lineLength;
64 | }
65 | if (nova.inDevMode()) {
66 | console.info(`LspRangeToRange() — Range Start: ${rangeStart}; Range End: ${rangeEnd}; Start > End? ${rangeStart > rangeEnd}`);
67 | }
68 | if (rangeStart < rangeEnd) {
69 | return new Range(rangeStart, rangeEnd);
70 | } else {
71 | return undefined;
72 | }
73 | // } else if (rangeStart > rangeEnd) {
74 | // return new Range(rangeEnd, rangeStart);
75 | // } else {
76 | // // if they're equal, we'll probably want to change this line only...
77 | // return new Range(rangeStart, rangeEnd + 1)
78 | // }
79 | };
80 |
81 | // Apply a TextDocumentEdit
82 | // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
83 | exports.ApplyTextDocumentEdit = (tde) => {
84 | if (tde && tde.textDocument && tde.edits) {
85 | // Obtain a Nova TextEditor for the document
86 | return nova.workspace
87 | .openFile(tde.textDocument.uri)
88 | .then((editor) => {
89 | // exports.ApplyTextEdits(editor, tde.edits);
90 | return exports.ApplyTextEditsRevamped(editor, tde.edits); // making an experiment
91 | })
92 | .catch((err) => {
93 | console.error('error opening file', err);
94 | });
95 | } else {
96 | console.info('no edits to apply, it seems');
97 | }
98 | };
99 |
100 | // Apply a TextEdit[]
101 | // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
102 | exports.ApplyTextEdits = (editor, edits) => {
103 | return editor
104 | .edit((tee) => {
105 | edits.reverse().forEach((e) => {
106 | var r0 = exports.LspRangeToRange(editor.document, e.range);
107 | var r1 = new Range(r0.start, r0.end);
108 | tee.replace(r1, e.newText);
109 | });
110 | })
111 | .then(() => {
112 | console.info(`${edits.length} changes applied to ${editor.document.path}`);
113 | });
114 | }
115 |
116 | // NovaPositionFromLSPRange calculates the position relative to LSP (line; character).
117 | // Conceptually similar to LspRangeToRange, but with a different purpose (see ApplyTextEditsRevamped).
118 | // Note: this will very likely blow up since calculations assume UTF-16 (don't you hate Microsoft?)
119 | // (gwyneth 20210406)
120 | exports.NovaPositionsFromLSPRangeElement = function(document, lspLine, lspCharacter) {
121 | const fullContents = document.getTextInRange(new Range(0, document.length));
122 | let position = 0;
123 | let chars = 0;
124 | const lines = fullContents.split(document.eol);
125 | for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
126 | const lineLength = lines[lineIndex].length + document.eol.length;
127 | if (lspLine === lineIndex) {
128 | position = chars + lspCharacter;
129 | // break; // we can save a few cycles
130 | return position; // get out of the loop as early as possible
131 | }
132 | chars += lineLength;
133 | }
134 | /* if (nova.inDevMode()) {
135 | console.info(`NovaPositionsFromLSPRangeElement() — LSP Line: ${lspLine}; LSP Column: ${lspCharacter}; Nova Position: ${position}`);
136 | }*/
137 | return position;
138 | }
139 |
140 | // ApplyTextEditsRevamped calculates if a bit of formatted has to be inserted, replaced, or removed.
141 | // Using ApplyTextEdits will just work for inserting formatted text; but we need a bit more logic in our case
142 | // See also https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-17.md#textEdit to understand how insert/replace/remove is signalled by the LSP (gwyneth 20210406)
143 | exports.ApplyTextEditsRevamped = (editor, edits) => {
144 | return editor.edit((tee) => { // tee - text editor edit (that's how Panic calls it!)
145 | edits.slice().reverse().forEach((e) => { // stupid, but gopls sends these in *reverse* order!! (gwyneth 20210407)
146 | // very, very inefficient for now, but we will improve later using just one loop (gwyneth 20210406)
147 | var startPosition = exports.NovaPositionsFromLSPRangeElement(editor.document, e.range.start.line, e.range.start.character);
148 | var endPosition = exports.NovaPositionsFromLSPRangeElement(editor.document, e.range.end.line, e.range.end.character);
149 |
150 | if (e.newText == null || e.newText == undefined || e.newText == "") { // this means we're going to _delete_ the characters in the range, and that the range must be valid
151 | var deletedRange = new Range(startPosition, endPosition -1);
152 | tee.delete(deletedRange);
153 | console.info(`Deleting text from (${e.range.start.line},${e.range.start.character}) to (${e.range.end.line},${e.range.end.character}) [${startPosition}-${endPosition}]`);
154 | } else if (startPosition == endPosition) { // this means insert a new range
155 | tee.insert(startPosition, e.newText);
156 | console.info(`Inserting «${e.newText}» at (${e.range.start.line},${e.range.start.character}) [${startPosition}]`);
157 | } else if (startPosition < endPosiiton) {
158 | var replacedRange = new Range(startPosition, endPosition -1);
159 | tee.replace(replacedRange, e.newText);
160 | console.info(`Replacing from (${e.range.start.line},${e.range.start.character}) to (${e.range.end.line},${e.range.end.character}) [${startPosition}-${endPosition}] with «${e.newText}»`);
161 | } else {
162 | console.error(`Something bad happened, we should have never reached this spot! We got LSP range: (${e.range.start.line},${e.range.start.character}) to (${e.range.end.line},${e.range.end.character}), Nova Range: [${startPosition}-${endPosition}], text: «${e.newText}»`);
163 | }
164 | });
165 | })
166 | .then(() => {
167 | console.info(`${edits.length} changes applied to ${editor.document.path}`);
168 | });
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/Completions/Go.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | go, go *:not(string,string *,comment,variable,regex,regex *)
6 | go.root-variables
7 | go.root-methods
8 | go.constants
9 | (?<!\.)\b[a-zA-Z]*
10 |
11 |
12 |
13 | go, go *:not(string,string *,comment,regex,regex *)
14 | go.global-properties
15 | \.([a-zA-Z]*)
16 |
17 |
18 |
19 | go, go *:not(string,string *,comment,regex,regex *)
20 | go.constructors
21 | \bnew\s+([a-zA-Z]*)
22 |
23 |
24 |
25 | go, go *:not(string,string *,comment,regex,regex *)
26 | go.action.properties
27 | \baction\.(\w*)
28 |
29 |
30 | go, go *:not(string,string *,comment,regex,regex *)
31 | go.context.properties
32 | \bcontext\.(\w*)
33 |
34 |
35 | go, go *:not(string,string *,comment,regex,regex *)
36 | go.lineStorage.properties
37 | \blineStorage\.(\w*)
38 |
39 |
40 | go, go *:not(string,string *,comment,regex,regex *)
41 | go.syntaxTree.properties
42 | \bsyntaxTree\.(\w*)
43 |
44 |
45 | go, go *:not(string,string *,comment,regex,regex *)
46 | go.itemizer.properties
47 | \bitemizer\.(\w*)
48 |
49 |
50 | go, go *:not(string,string *,comment,regex,regex *)
51 | go.textPreferences.properties
52 | \btextPreferences\.(\w*)
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | (;)|[^;]
62 | (?1::;)
63 |
64 |
65 |
66 |
67 |
68 |
69 | ([^\n\r]?)|[\n\r]
70 | (?1:: ${1:condition}:)
71 |
72 |
73 |
74 |
75 |
76 |
77 | (;)|[^;]
78 | (?1::;)
79 |
80 |
81 |
82 |
83 |
84 |
85 | (:)|[^:]
86 | (?1:::)
87 |
88 |
89 |
90 |
91 |
92 |
93 | (\s*\{)|\s*[^{]|[^\s{]
94 | (?1:: {
95 | $0
96 | })
97 |
98 |
99 |
100 |
101 |
102 |
103 | (\s*\()|\s*[^(]|[^\s(]
104 | (?1:: (${1:${2:var i = 0}; ${3:i < count}; ${4:i++}}\) {
105 | $0
106 | })
107 |
108 |
109 |
110 |
111 |
112 |
113 | (\s*\()|(\s*\{)|\s*[^(]|[^\s(]
114 | (?1::(?2: ($0\): ($1\) {
115 | $0
116 | }))
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | (\s*\()|\s*[^(]|[^\s(]
125 | (?1:: ($1\) {
126 | $0
127 | })
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | (\s*\()|(\s*\{)|\s*[^(]|[^\s(]
138 | (?1::(?2: ($0\): ($1\) {
139 | $0
140 | }))
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | (\s*\(|\s+[a-zA-Z_$])|\s*[^(a-zA-Z_$]|[^\s(]
150 | (?1:: ${1:name}($2\) {$3})
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | (\()|[^(]
179 | (?1::($1\))
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 | (\()|[^(]
227 | (?1::(${1:string}\))
228 |
229 |
230 |
231 |
232 |
233 | (\()|[^(]
234 | (?1::(${1:sliceType}, ${2:length}, ${3:capacity}\))
235 |
236 |
237 |
238 |
239 |
240 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## Version 0.4.3
2 | - Several new improvements on syntax checking; a lot more is being correctly highlighted (but there is even more that isn't; see [README.md](README.md)).
3 | - Adding the @all-contributors GitHub bot to give people a bit more credit. They deserve it!
4 | - Edited some of the (outdated) information on the README.
5 | - Added a special class on my sister project, the Nord theme extension, to provide highlighting for delimiters.
6 | - More crazy tests on `basictest.go` to catch common syntax highlighting errors (there are many).
7 | - Added a funding button, let's see if it works!
8 | - TODO(gwyneth): Try to understand why the imports aren't properly formatted by `gopls`, even if the rest is...
9 |
10 | ## Version 0.4.2
11 |
12 | - Thanks to @logan's changes on correctly implementing Markdown hover tags!
13 |
14 | ## Version 0.4.1
15 |
16 | - Added checkbox on preferences to use https://staticcheck.io/ to do additional code analysis.
17 |
18 | ## Version 0.4.0
19 |
20 | - Nova 5.1 is out and it supports Language Servers much better! Enjoy the quasi-IDE environment!
21 | - Added support for editing `go.mod` files. Note: If you've installed [VLC](https://www.videolan.org/vlc/), `.mod` files are thought to be audio files, thus they're not easily opened with Nova (added `Tests/go.mod.sample` to test it out).
22 | - *Big* cleaning up of the syntax definition file; all regular expressions have been tested, one by one, and fixed in uncountable cases. Even capturing complex numbers works! Much better syntax highlighting. Incidentally, issue [_#1_](https://github.com/GwynethLlewelyn/Go.novaextension/issues/1) got fixed, after 7 months...
23 | - The **Editor > Go** menu options for text formatting and reorganising imports work about 80% of the cases. They are now interfacing correctly with `gopls` and retrieving proper replacement information (who'd think that Google would send all updates _in reverse order_?!). So, no need to run any additional external commands for those operations; `gopls` is _supposed_ to do all the work from now on.
24 | - Sadly, the option to format/optimise imports on _saving_ is **not** functional. There is an **experimental** checkbox for it on the preferences, but **DO. NOT. CHECK. IT.**. It will _literally_ destroy your files when saving them. Basically, it runs the formatter twice, for some unfathomable reason, and I couldn't find a way to prevent that.
25 |
26 | ### To-do:
27 | - Add a checkbox to get your code additionally validated by https://staticcheck.io/. It's easy enough to set up — it's fully integrated by Google in `gopls` itself!
28 | - Make the _new_ code to convert from Nova ranges into LSP ranges a bit more efficient; or pester Panic to do that conversion available via the JS API (after all, they use it internally!). Note that this is mostly a proof-of-concept version (it's still alpha code, remember? 😉) just to fix an annoying bug that comes from wrong assumptions about `gopls` (other Language Servers seem to work... all have their own quirks).
29 | - Figure out _why_ `gopls` is running *twice* when saving (thus thrashing everything), although just once when called from the menu options. I've clearly hit a personal limit; this is beyond my ability and knowledge to understand at the moment.
30 | - Figure out how to install VLC and still have Nova opening `go.mod` files without thinking they're video files!
31 |
32 | ## Version 0.3.5
33 |
34 | - Basically just bumping the version to remove the warning about not being possible to update this extension via the Nova Extension Library. Panic fixed everything!
35 | - Amazingly, the reorganisation of import files, via `gopls`, seems to work! 😲 Try to mouse-select your imports and click on **Editor > Go > Organize Imports** — this should do *something*
36 | - The extension still crashes if it is deactivated/reactivated; also, it now might get a bit confused when figuring out if the `gopls` server is running or not. Sometimes it requires a reset (via the check box on Preferences).
37 |
38 | ## Version 0.3.4
39 |
40 | - Many of the crashes are related to objects which haven't been correctly initialised, or, worse, released (google for `KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED`); this release attempts to fix some of those errors
41 | - Added more `try{...}catch` constructs in order to see some (possibly hidden) errors _before_ Nova crashes
42 | - Slightly changed a few functions to better deal with the differences in handling extensions with a Language Server, compared to earlier Nova versions
43 |
44 | ## Version 0.3.3
45 |
46 | - Finally figured out how to turn hover Markdown off! Next step: figuring out how to _fix_ it...
47 | - Banner logo is back, I thought it made a difference when downloading the extension, but no: the problem lies elsewhere on Nova's servers (as of writing, they're on it and trying to fix things)
48 | - Fixed a few extra things, again, to comply with the extension template
49 | - Tried to incorporate @jfieber's changes (a few options now appear on the Editor menu, but they don't do much; I know that they're _working_, since they _do_ get `gopls` to write things on the log)
50 | - Updated license to display contributors (Nova won't show it, though)
51 | - Updated README with some extra thanks and a warning that downloading this extension/updating it may fail due to some as-yet-unsolved issues with Panic's Nova Extension Library server (this plugin is not the only one being affected)
52 |
53 | ## Version 0.3.2
54 |
55 | - Changed some of the code to comply better with the latest extension template included with Nova 4.3 — this may, or may not, fix some crashing issues (because things were called differently before)
56 | - Force `gopls` to use plain text instead of Markdown, on a single line; it's not as nice, but at least it works
57 | - Apparently there was some issue with Nova's library extension server earlier on, and that's why the earlier version failed, it should get fixed sooner or later
58 |
59 | ## Version 0.3.1
60 |
61 | - Bumping the version because something went wrong with the upload
62 |
63 | ## Version 0.3.0
64 |
65 | - Major rewriting of the code base, mostly thanks to the generous work provided by @jfieber and @seripap. Thanks guys!
66 | - LSP interfacing with `gopls` now works! But don't expect miracles, we haven't still figured out all of it. Use `brew install gopls`.
67 | - A few extension preferences were added by @jfieber (namely, turning LSP on and off, etc.); also, for development purposes, `gopls` will write some (cryptic) logs under `/tmp/gopls.log`
68 | - Added more references to licenses; we are now including open-source code from Microsoft (I never though I'd ever write this in my lifetime! 😳🤓)
69 | - Added more blahblahblah to the [README.md](README.md) (and a few markdown tricks!)
70 | - New logo (ok, this is trivial, but I'm trying to keep up with Panic's re-styling! 😅)
71 | - To-do: figure out why `gopls` sends raw Markdown that Nova doesn't seem to understand
72 | - To-do: understand why the extension crashes so often (at least in dev mode); it's possible that some cleanup code is missing and/or broken
73 | - Tested under Nova 4.3
74 |
75 | ## Version 0.2.1
76 |
77 | - Small JSON change from 'vendor' to 'organization' according to the new specs for the Nova Beta 1.0b18 (195066)
78 | - Tried to add `gopls` again, but couldn't
79 |
80 | ## Version 0.2.0
81 |
82 | - Added gazillions of changes, based on several different templates and the manuals of a competitor editor which uses similar syntax (which was originally based on the templates for Coda!)
83 | - While this produces slightly better matching, there are tons of rules that never get activated but I don't know why
84 | - Added a Smarty-like parser for Go Templates (it's basically the same concept with some tiny, Go-specific changes)
85 | - Added some test files, please ignore them, they're not meant to be 'working code' (nor even valid one)
86 | - Had to remove `gopls` because it's too big! You can download it from https://github.com/golang/tools/tree/master/gopls
87 |
88 | ## Version 0.1.6 (never released)
89 |
90 | - With the new Nova Beta update to 1.0b17 (Build 190148) it looks like the executable for `gopls` lost its executable flag; if that did make a difference or not is beyond me, but I recompiled `gopls` again, with newer libraries.
91 | - When clicking on the syntax inspector button (at the bottom of each pane, the tiny 'target' icon which is to the left of the 'current symbol'), now 'something' happens when randomly clicking on Go code (i.e. there is a modal popup box that shows some information). If that's the desired behaviour or not... I have no idea.
92 |
93 | ## Version 0.1.5
94 |
95 | - Make `.mod` files (e.g. `go.mod`) be part of the extensions, or else they will be seen as music files
96 |
97 | ## Version 0.1.4
98 |
99 | Cleaning up the logs when instance is deactivated.
100 |
101 | ## Version 0.1.3
102 |
103 | - Bumped version again
104 | - Some more experiments on the test file `basictest.go`
105 |
106 | ## Version 0.1.2
107 |
108 | - Slight bug on `main.js` (missing bracket)
109 |
110 | ## Version 0.1.1
111 |
112 | - Version 0.1.0 was successfully uploaded to the Extensions Library!!
113 | - Go LSP seems not to be working at all
114 | - Lots of errors in syntax highlighting (e.g. variable declaration)
115 |
116 | ## Version 0.1.0
117 |
118 | - After checking the many XML files, I found three minor bugs, and now the syntax highlighting not only works, but it shows up as a 'valid' language on all the places that it ought to show up!
119 | - Apparently, you cannot have any images under the `Images/` folder, or uploading to the Extension Library does _not_ work
120 | - Still working to fix the connection to the Go LPS (it's not being launched right now, but I have some ideas to fix it...)
121 |
122 | ## Version 0.0.2
123 |
124 | - Syntax definition XML based on Nova JavaScript, using definitions from the old Coda 2 Go mode
125 | - Tried to add Go LPS support
126 | - Added the logo and a few things
127 |
128 | ## Version 0.0.1
129 |
130 | Initial release — based on the original Coda 2 Go mode
131 |
--------------------------------------------------------------------------------
/Scripts/main.js:
--------------------------------------------------------------------------------
1 | var lsp = require('lsp.js');
2 | var langserver = null;
3 |
4 | exports.activate = function () {
5 | // Do work when the extension is activated
6 | langserver = new GoLanguageServer();
7 | };
8 |
9 | exports.deactivate = function () {
10 | // Clean up state before the extension is deactivated
11 | if (langserver) {
12 | langserver.deactivate(); // conforming to newer Nova templates
13 | langserver = null;
14 | }
15 | // shouldn't we remove /tmp/gopls.log? (gwyneth 20210129)
16 | nova.fs.remove('/tmp/gopls.log'); // if it doesn't exist, does nothing (20210130)
17 | };
18 |
19 | class GoLanguageServer {
20 | constructor() {
21 | // From the new template for extensions using LSP (gwyneth 20210203)
22 | // Observe the configuration setting for the server's location, and restart the server on change
23 | nova.config.observe('go-nova.gopls-path', function(path) {
24 | this.start(path);
25 | }, this);
26 |
27 | // Handle preference change for enable/disable.
28 | nova.config.onDidChange(
29 | 'go-nova.enable-gopls',
30 | function (current, previous) {
31 | if (current) {
32 | this.start();
33 | } else {
34 | this.stop();
35 | }
36 | },
37 | this
38 | );
39 |
40 | // Handle preference change for gopls path.
41 | nova.config.onDidChange(
42 | 'go-nova.gopls-path',
43 | function (current, previous) {
44 | // If the user deletes the value in the preferences and presses
45 | // return or tab, it will revert to the default of 'gopls'.
46 | // But on the way there, we get called once with with current === null
47 | // and again with current === previous, both of which we need to ignore.
48 | if (
49 | current &&
50 | current != previous &&
51 | nova.config.get('go-nova.enable-gopls', 'boolean')
52 | ) {
53 | console.info('Restarting gopls due to path change');
54 | this.stop();
55 | // Hack: until we can reliably determine when the service is
56 | // actually stopped, pause a few ticks to already running error.
57 | setTimeout(() => {
58 | this.start();
59 | }, 2000);
60 | }
61 | },
62 | this
63 | );
64 |
65 | // Start on load, if the preferences say so.
66 | if (nova.config.get('go-nova.enable-gopls', 'boolean')) {
67 | this.start();
68 | }
69 | }
70 |
71 | deactivate() {
72 | this.stop();
73 | }
74 |
75 | start(path) { // seems that it now requires an extra variable...
76 | // Check if gopls is already running; this is acording to the new extension template (gwyneth 20210202)
77 | if (this.languageClient) {
78 | this.languageClient.stop();
79 | nova.subscriptions.remove(this.languageClient); // redundant, .stop() allegedly does this, but that's what we've got on the new template... (gwyneth 20210202)
80 | }
81 |
82 | // Basic server options
83 | var serverOptions = {
84 | path: nova.config.get('go-nova.gopls-path', 'string') || 'gopls' || path,
85 | args: ['serve'],
86 | };
87 |
88 | // An absolute path or use the search path?
89 | if (serverOptions.path.charAt(0) !== '/') {
90 | serverOptions.args.unshift(serverOptions.path);
91 | serverOptions.path = '/usr/bin/env';
92 | }
93 |
94 | if (nova.inDevMode()) {
95 | serverOptions.args = serverOptions.args.concat([
96 | '-rpc.trace',
97 | '-logfile',
98 | '/tmp/gopls.log',
99 | ]);
100 | console.info('gopls server options:', JSON.stringify(serverOptions));
101 | }
102 |
103 | // Recent versions of Nova can also send initializationOptions. The syntax
104 | // is not obvious, because Microsoft and Google use so confusing notations
105 | // which are mutually incomprehensible (MS uses TypeScript, Google uses Go).
106 | // See https://github.com/golang/tools/blob/master/gopls/doc/settings.md
107 | // (gwyneth 20210131)
108 | var clientOptions = {
109 | syntaxes: ['go'],
110 | initializationOptions: {
111 | // "hoverKind": "SingleLine", // I know that "SingleLine" works — other options seem to _always_ trigger Markdown (gwyneth 20210202) for the information, which somehow Nova dislikes and does not render (gwyneth 20210407)
112 | "hoverKind": "SynopsisDocumentation", // available since Nova 6...? (gwyneth 20210422)
113 | "staticcheck": nova.config.get('go-nova.use-staticcheck', 'boolean'), // using staticcheck.io for further analysis (gwyneth 20210407)
114 | "usePlaceHolders": true // trying out which one works (gwyneth 20210203)
115 | }
116 | };
117 |
118 | if (nova.inDevMode()) {
119 | console.info("gopls client options:", JSON.stringify(clientOptions));
120 | }
121 |
122 | var client = new LanguageClient(
123 | 'gopls',
124 | 'Go Language Server',
125 | serverOptions,
126 | clientOptions
127 | );
128 |
129 | try {
130 | // Start the client
131 | client.start();
132 |
133 | // Add the client to the subscriptions to be cleaned up
134 | nova.subscriptions.add(client);
135 | this.languageClient = client;
136 | } catch (err) {
137 | // If the .start() method throws, it's likely because the path to the language server is invalid
138 | console.error("Couldn't start the gopls server; please check path. Error was: ", err);
139 | }
140 |
141 | // Code by @apexskier introduced by @jfieber
142 | // Registers the commands that can be invoked from the menu as well as the format-on-save
143 | try {
144 | this.commandJump = nova.commands.register('go.jumpToDefinition', jumpToDefinition);
145 | this.commandOrganizeImports = nova.commands.register('go.organizeImports', organizeImports);
146 | this.commandFormatFile = nova.commands.register('go.formatFile', formatFile);
147 | // The code below comes from @jfieber (slightly adapted) (gwyneth 20210406)
148 | this.formatOnSave = nova.workspace.onDidAddTextEditor((editor) => {
149 | editor.onDidSave(() => {
150 | console.log('Saved complete');
151 | });
152 | editor.onWillSave((editor) => {
153 | if (editor.document.syntax === 'go') {
154 | if (nova.config.get('go-nova.format-on-save', 'boolean')) {
155 | console.info('Entering FormatOnSave for "' + editor.document.uri + '"...');
156 | try {
157 | // nova.commands.invoke("go.formatFile", editor); // this is how @apexskier calls the function (20210408)
158 | formatFile(editor);
159 | } catch(err) {
160 | console.error("Re-formatting failed miserably");
161 | }
162 | }
163 | }
164 | }, this);
165 | }, this);
166 |
167 | } catch(err) {
168 | console.error("Could not register editor commands: ", err);
169 | }
170 | }
171 |
172 | // According to the revised Nova documentation, we should only get a stop() iff the server is still
173 | // running; but we nevertheless keep the old code around anyway (gwyneth 20210406)
174 | stop() {
175 | if (this.languageClient) {
176 | try {
177 | if (this.commandJump && isDisposable(this.commandJump)) {
178 | this.commandJump.dispose();
179 | }
180 | if (this.commandOrganizeImports && isDisposable(this.commandOrganizeImports)) {
181 | this.commandOrganizeImports.dispose();
182 | }
183 | if (this.commandFormatFile && isDisposable(this.commandFormatFile)) {
184 | this.commandFormatFile.dispose();
185 | }
186 | if (this.formatOnSave && isDisposable(this.formatOnSave)) {
187 | this.formatOnSave.dispose();
188 | }
189 | } catch(err) {
190 | console.error("While stopping, disposing the editor commands failed: ", err);
191 | }
192 | try {
193 | this.languageClient.stop();
194 | nova.subscriptions.remove(this.languageClient);
195 | this.languageClient = null;
196 | } catch (err) {
197 | console.error("Could not stop languageClient and/or remove it from subscriptions: ", err);
198 | }
199 | } else {
200 | console.error("For some reason, Nova tried to stop a languageClient that wasn't running.");
201 | }
202 | }
203 |
204 | client() {
205 | return this.languageClient;
206 | }
207 | }
208 |
209 | // Code by @apexskier introduced by @jfieber
210 | // This may use some code developed by Microsoft — see [Microsoft Public License (MS-PL)](https://opensource.org/licenses/MS-PL)
211 | function organizeImports(editor) {
212 | if (langserver && langserver.client()) {
213 | var cmd = 'textDocument/codeAction';
214 | var cmdArgs = {
215 | textDocument: {
216 | uri: editor.document.uri
217 | },
218 | range: lsp.RangeToLspRange(editor.document, editor.selectedRange),
219 | context: { diagnostics: [] }
220 | };
221 |
222 | langserver.client().sendRequest(cmd, cmdArgs).then((response) => {
223 | // console.info(`${cmd} response:`, response);
224 | if (response !== null && response !== undefined) {
225 | response.forEach((action) => {
226 | if (action.kind === "source.organizeImports") {
227 | console.info(`Performing actions for ${action.kind}`);
228 | action.edit.documentChanges.forEach((tde) => {
229 | lsp.ApplyTextDocumentEdit(tde);
230 | });
231 | } else {
232 | console.info(`Skipping action ${action.kind}`);
233 | }
234 | });
235 | }
236 | }).catch(function(err) {
237 | console.error(`${cmd} error!:`, err);
238 | });
239 | } else {
240 | console.error("organizeImports() called, but gopls language server is not running");
241 | }
242 | }
243 |
244 | function formatFile(editor) {
245 | if (langserver && langserver.client()) {
246 | var cmd = 'textDocument/formatting';
247 | var cmdArgs = {
248 | textDocument: {
249 | uri: editor.document.uri
250 | },
251 | options: { // https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-17.md#document-formatting-request--leftwards_arrow_with_hook (gwyneth 20210406)
252 | tabSize: editor.tabLength,
253 | insertSpaces: editor.softTabs != 0
254 | }
255 | };
256 | if (nova.inDevMode()) {
257 | console.info("formatFile(): cmdArgs is ", JSON.stringify(cmdArgs, undefined, 4));
258 | }
259 | langserver.client().sendRequest(cmd, cmdArgs).then((response) => {
260 | if (nova.inDevMode()) {
261 | console.info(`formatFile(): '${cmd}' response:`, JSON.stringify(response, undefined, 4));
262 | }
263 | if (response !== null && response !== undefined && response !== []) {
264 | // lsp.ApplyTextEdits(editor, response);
265 | lsp.ApplyTextEditsRevamped(editor, response); // trying to deal with replace/delete/insert issues (gwyneth 20210406)
266 | }
267 | }).catch(function(err) {
268 | console.error(`formatFile(): ${cmd} error! - `, err);
269 | });
270 | } else {
271 | console.error("formatFile() called, but gopls language server is not running");
272 | }
273 | }
274 |
275 | function jumpToDefinition(editor) {
276 | if (
277 | langserver === null ||
278 | langserver.client() === null ||
279 | langserver.client() === undefined
280 | ) {
281 | console.info("jumpToDefinition() called, but gopls language server is not running");
282 | return;
283 | }
284 | var selectedRange = editor.selectedRange
285 | selectedPosition =
286 | (_a = lsp.RangeToLspRange(editor.document, selectedRange)) === null ||
287 | _a === void 0
288 | ? void 0
289 | : _a.start
290 | if (!selectedPosition) {
291 | nova.workspace.showWarningMessage(
292 | "Couldn't figure out what you've selected."
293 | );
294 | return;
295 | }
296 | var params = {
297 | textDocument: {
298 | uri: editor.document.uri,
299 | },
300 | position: selectedPosition,
301 | }
302 | var jump = langserver.client().sendRequest('textDocument/definition', params)
303 | // {"uri":"file:///opt/brew/Cellar/go@1.14/1.14.7/libexec/src/fmt/print.go","range":{"start":{"line":272,"character":5},"end":{"line":272,"character":12}}}
304 |
305 | jump.then(function (to) {
306 | if (to !== null) {
307 | if (to.length > 0) {
308 | var target = to[0]
309 | console.info('Jumping', JSON.stringify(to[0]))
310 | nova.workspace
311 | .openFile(target.uri)
312 | .then(function (targetEditor) {
313 | // When Nova first opens a file, the callback gets an undefined editor,
314 | // which is most likely a bug. Usually works the second time.
315 | if (targetEditor === undefined) {
316 | console.error('Failed to get TextEditor, will retry')
317 | nova.workspace
318 | .openFile(target.uri)
319 | .then(function (targetEditor) {
320 | targetEditor.selectedRange = lsp.LspRangeToRange(
321 | targetEditor.document,
322 | target.range
323 | )
324 | targetEditor.scrollToCursorPosition()
325 | })
326 | .catch(function (err) {
327 | console.error(
328 | 'Failed to get text editor on the second try',
329 | err
330 | )
331 | })
332 | } else {
333 | targetEditor.selectedRange = lsp.LspRangeToRange(
334 | targetEditor.document,
335 | target.range
336 | )
337 | targetEditor.scrollToCursorPosition()
338 | }
339 | })
340 | .catch(function (err) {
341 | console.info('Failed in the jump', err);
342 | })
343 | }
344 | }
345 | })
346 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](#contributors-)
4 |
5 |
6 | # Go Language Definition for Nova
7 |
8 | An ongoing attempt to build a Go language definition for the [Panic Nova](https://panic.com/nova) editor, using the Language Server Protocol (LSP) with Google's official `gopls` language server for Go.
9 |
10 | **Note:** v0.4.3 is still an **alpha** version with working syntax highlighting and extra goodies from using the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), but it is plagued with some unstability issues, often leading to a crash. See below for some guidelines.
11 |
12 | [@jfieber](https://github.com/jfieber) added a 'Go' menu from which some functionality can be selected; in many cases, it will attempt to do a re-formatting according to Go's best practices, as well as organise imports. This is not working 100% of the time, though (and we still don't know why).
13 |
14 | Worst case scenario: if _nothing_ here works for you, you might try to use Spicer Matthews' own [GoTools](nova://extension?id=cloudmanic.GoTools "This link will open only in Nova") extension. The syntax highlighting should be similar — and that extension should _not_ crash!
15 |
16 | ## Installation
17 |
18 | Once activated, files ending in `*.go` should automatically be recognised (and formatted) as Go language files. Similarly, `*.tmpl` [Go template files](https://golang.google.cn/pkg/html/template/) will also be recognised[1](#f1), and from version 0.4.0 onwards, even `go.mod` gets its own syntax highlighting.
19 |
20 | Additional Go specific features are available by installing the [Go Language Server](https://github.com/golang/tools/blob/master/gopls/README.md), `gopls`. This will turn Nova into a quasi-IDE for Go!
21 |
22 | If you use [Homebrew](https://brew.sh/) to install your packages, all you need is to type:
23 |
24 | `brew install gopls`
25 |
26 | If not, you can install it as described [here](https://github.com/golang/tools/blob/master/gopls/doc/user.md#installation).
27 |
28 | Then tick the *Enable Language Server* checkbox in the Preferences for this extension. If `gopls` is (correctly) installed in your search `PATH`, the extension should find it. If it is elsewhere, set that where in the Preferences for this extension as well. Note that Nova's language server support and `gopls` are both new and evolving. Many things may _not_ work quite right yet.
29 |
30 | When checking for syntax errors, `gopls` can optionally use https://staticcheck.io/ for additionally analysis; there is a checkbox on Preferences to allow the extra checking.
31 |
32 | **WARNING:** (aye, again) If you click on *Format/Organise Imports when saving file* to get `gopls` to automatically reformat your code when saving, be warned: it _really_ does corrupt the files! I'm _not_ joking. The option is there just because I'm hoping to try it out until I find a way to fix the issue.
33 |
34 | More information on the capabilities of `gopls` as well as its design/implementation considerations can be found [on GitHub](https://github.com/golang/tools/blob/master/gopls/doc/design/design.md). As Nova gets better and better integration with Language Servers, and as Google also improves `gopls` to be more compliant with Microsoft's LSP definition, a lot of functionality will appear 'automagically' by simply upgrading Nova or `gopls`.
35 |
36 | ## Disclaimers
37 |
38 | I'm _still_ a bit clueless about how the syntax highlighting engine/parser actually parses the language files (although some things are starting to make more sense). There is _very little_ 'official' documentation; however, on the site for an editor made by a competitor, it looks like they have used something very similar, and — allegedly! — based on the original Coda syntax (not Coda 2!). Apparently, Nova uses a variant of the same parser 'family'.
39 |
40 | This version includes a `Go.xml` Syntax template which was cobbled together out of a _lot_ of sources, namely, the Coda 2 Go language definition files; the Nova (included) language files for PHP, TypeScript (because Go is also strongly typed), JavaScript, and even C++; I've made extensive use of https://regex101.com/ to check the correctness of most (if not all) regular expressions needed for the syntax highlighting; and I'm also very quite thankful for the (incomplete) work made by [@ambelovsky](https://github.com/ambelovsky/espresso-golang) (on GitHub), when adapting the old Coda syntax for the editor from the competition. Several of his comments have been copied and incorporated. His work was sadly not completed, still had a lot of errors (basically he used the template for JavaScript), and, at the date of writing, was abandoned nine years ago. Nevertheless, it had lots of very interesting structures to parse the Go language (while leaving several others unimplemented). While strongly _inspired_ by his work, this is not merely a copy & paste — many adaptations were required to get some of the functionality to actually work. A lot still doesn't (it gets silently ignored) and I still haven't figured out how to deal with them...
41 |
42 | Additionally, I've included a Syntax template for Go Templates. It's almost exactly the same as the syntax for Smarty templates (which I have been using) with some tiny changes, which I hope to have correctly implemented.
43 |
44 | The new, incuded syntax highlighter for `go.mod` files was mostly an experiment. It works quite well, though, since the language definition for that is so simple.
45 |
46 | Although the current version includes a Completions file, I don't see any kind of completion happening (except for closing braces). I've tried to figure out how the syntax of the Completions file works, but it's even more obscure (to me) than the actual Syntax file. The two are also possibly related — through common identifiers — but I fail to understand exactly how the two 'play' together. I've gotten access to a few more resources explaining this format, so maybe I'll give it another try.
47 |
48 | Also, Nova — unlike Coda — allows extensions to use the [Language Server Protocol](https://langserver.org/) (like their closest competitors do), a Microsoft-promoted effort enabling a '*write once, reuse often*' philosophy for writers of syntax checkers. In other words, the hard work is put into creating a _functioning_ LSP 'server' (basically an application that reads a file in a specific language, or parts of a file, and figures out if it has any syntax errors) by the community of syntax checkers. _Then_ editor plugins (of all kinds, not only desktop apps) can interface with such a server in order to get syntax checking. In theory, it's a very easy way to quickly expand the ability for a code editor to accept gazillions of languages without requiring the developers to spend days and nights coding as many syntax checkers as possible. With new languages coming up all the time, many becoming fashionable for a few years and disappearing shortly afterwards, this method ensures that editor developers are not wasting their precious time. It also means that updating syntax checkers for upcoming new versions of a specific language will not require any coding — just upgrade the LSP server. And, finally, it also means that _all_ code editors will check syntax in the _same, predictable_ way (and also that _all_ will get upgraded to the latest version of the syntax almost immediately), which means that, if you switch editors, the 'new' editor will _already_ support the latest version of your favourite programming language _and_ syntax checking will work in pretty much the same way...
49 |
50 | Therefore, this extension can optionally use the official (Google-supported) [Go Language Server](https://github.com/golang/tools/blob/master/gopls/README.md) if you install it as described in the Installation section above. Thanks to recent improvements in Nova, it's now almost fully functional. Enjoy 😌
51 |
52 | The LSP specification is still very quirky. Microsoft developed the LSP specifically for Visual Studio Code, their free, open-source, cross-platform editor, thus allowing non-Microsoft-specific languages to be as easily integrated with their editor. However, the Microsoft specifications are *very* Microsoft-centric, and the Google team behind `gopls` grumbles and complains about several ambiguous descriptions in the protocol, and the choices they've made to implement the (complex) specifications. Sadly, though, those specifications are *very* Google-centric (notice the pattern?) and they don't match easily with the Microsoft ones. And on top of all that, we have to deal with Panic's own implementation of LSP support — which is (at the time of writing!) a bit obscure, a bit opaque, and not exactly super-well-documented (namely, at least for me, it's not obvious what Nova does on its own and what the extension developer has to do). We have to take hints from the very few others who travelled the same road and try to figure out how they've done it.
53 |
54 | Note that Nova logs many interactions with the language server in the Extension Console, and if you run this extension in "developer mode" (see the *Extension Development* item in Nova's *General* preferences) `gopls` will write logs to `/tmp/gopls.log` but these can be quite a bit cryptic.
55 |
56 | In conclusion: all of the above is still very much a _work in progress_ — or rather, a _lot_ of work in progress. There is far less functionality which actually does anything than lots of files with rules that are _supposed_ to do _something_ but... don't. Therefore, _caveat utilitor_.
57 |
58 | Suggestions and bug reports are more than welcome, but please take into account that I'm new to all of this, and might not be able to even _understand_ most of your issues, much less _fix_ them! But I'm learning...
59 |
60 | ## Well-known bugs
61 |
62 | ### Syntax Checker bugs
63 |
64 | 1. On function definitions, the return values are not properly formatted (not even recognised by Nova)
65 | 2. Similarly, the `return` keyword will confuse the formatting of the ensuing expressions
66 | 3. On function definitions, arguments such as `(a,b integer)` _will_ be correctly formatted, but they are on the completely wrong scope (compare it with writing `(a integer, b integer)` instead)
67 | 4. Type declaration is still a work-in-progress; it's now foldable, but doesn't work correctly (getting it right is tough!)
68 | 5. Even variable declaration is... sketchy, at best. Some instances of it work; most don't
69 | 6. No type casting done (yet)
70 | 7. `make` and `append` aren't done yet
71 |
72 | ### Go Language Server bugs
73 |
74 | 1. Right now, the one issue that baffles me most is why the imports formatter does not work properly (i.e. the equivalent functionality to `goimports` which is allegedly built-in into the `gopls` Language Server)! It still has a very serious bug when figuring out what exactly to delete and shuffle around. Don't try it out without saving your files properly!
75 | 2. As said before, do **NOT** turn on the automatic formatting when saving! Until this issue isn't fixed, that option is essentially there only for the purpose of allowing others to do some testing. It's _not_ meant for anything else!
76 | 3. The `Go` menu (either from the top bar or by right-clicking on the text) runs the formatter most of the time, without crashing. Sometimes it does nothing; sometimes you have to select the whole range you wish to format in order to get it working. This is still a bit unpredictable, although I can't understand why it doesn't work _some_ times, while in _most_ cases, it has no issue whatsoever (even on the same, unchanged code!).
77 | 4. If you're plagued with extension crashes, just _un_check the *Enable Language Server* checkbox on the Preferences for this extension. You will still get Go syntax highlighting (and some auto-completion), but the additional goodies provided by LSP will be turned off.
78 | 5. There are a few hooks allowing you to *theoretically* run some post-formatting tools to comply with Google's style guidelines for Go, as well as a way to check that all imports are properly referenced, etc. With this version, there is no documentation yet for *how* to activate those extra features, but hopefully this will be addressed in the future... eventually.
79 |
80 | ## My GPG Fingerprint
81 |
82 | In case you need it to send me encrypted emails:
83 |
84 | > CE8A 6006 B611 850F 1275 72BA D93E AA3D C4B3 E1CB
85 |
86 | ---
87 |
88 | 1 I based that parser on the [PHP Smarty templates](https://www.smarty.net/) — Go's own template syntax is similar.[↩](#a1)
89 |
90 | ## Contributors ✨
91 |
92 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
93 |
94 |
95 |
96 |
97 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
112 |
--------------------------------------------------------------------------------
/Syntaxes/Go.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Go
5 | compiled
6 | go
7 | go
8 |
9 |
10 |
11 |
12 | go
13 |
14 |
15 |
16 |
17 | (\{[^}\"']*$)|(\[[^\]\"']*$)|(\([^)\"']*$)
18 |
19 |
20 | ^\s*(\s*\/\*.*\*\/\s*)*[\}\]\)\\]
21 |
22 |
23 |
24 |
25 |
26 | //
27 |
28 |
29 |
30 | /*
31 |
32 |
33 | */
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | (\/\/)(.*)$
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | \/\*
98 |
99 |
100 |
101 | \*\/
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | \{
114 |
115 |
116 |
117 | \}
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | (func)\s+(main|init)
137 |
138 |
139 |
140 |
141 | (?<=\})
142 |
143 |
144 |
145 | (?=\b(?:func|if|else|while|for|range)\b)
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | (func)\s+([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)
158 |
159 |
160 |
161 |
162 | (?<=\})
163 |
164 |
165 |
166 | (?=\b(?:func|if|else|while|for|range)\b)
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | \b(type)\s+([a-zA-ZÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+(struct)\b
182 |
183 |
184 |
185 |
186 |
187 |
188 | (?<=\})
189 |
190 |
191 |
192 | (?=\b(?:func|if|else|while|for|range)\b)
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | (func)\s+(\()([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+((\*?)[A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s*(\))\s+([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | (?<=\})
216 |
217 |
218 |
219 | \(?=\b(?:func|if|else|while|for|range)\b\)
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | (func)(?=\s*\()
234 |
235 |
236 |
237 | (?<=\})
238 |
239 |
240 |
241 | (?=\b(?:func|if|else|while|for|range)\b)
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 | \(
258 |
259 |
260 |
261 | \)
262 |
263 |
264 |
265 |
266 | (?=\b(?:func|if|else|while|for)\b)
267 |
268 |
269 |
270 |
271 | ,
272 |
273 |
274 |
275 |
276 | (\.\.\.)\b([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b
277 |
278 |
279 |
280 |
281 |
282 | (?<!\=)\b([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+(\*?)(\[\d*\])?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 | [!\(]\b(\*?)(\[\d*\])([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b[!\(]
299 |
300 |
301 |
302 |
303 |
304 |
305 | \(
306 |
307 |
308 |
309 | \)
310 |
311 |
312 |
313 |
314 | (?=\b(?:func|if|else|while|for)\b)
315 |
316 |
317 |
318 | ,
319 |
320 |
321 |
322 |
323 | (?<!\=)\b([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+(\*?)(\[\d*\])([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 | \{
343 |
344 |
345 |
346 | \}
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | break
361 | case
362 | chan
363 | const
364 | continue
365 | default
366 | defer
367 | else
368 | fallthrough
369 | for
370 | func
371 | go
372 | goto
373 | if
374 | import
375 | interface
376 | map
377 | package
378 | range
379 | return
380 | select
381 | struct
382 | switch
383 | type
384 | var
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 | nil
395 |
396 |
397 |
398 |
399 | true
400 | false
401 |
402 |
403 |
404 |
405 | iota
406 |
407 |
408 |
409 | \b0(x|X)[a-fA-F0-9]+\b
410 |
411 |
412 | \b0[0-7]+\b
413 |
414 |
415 |
416 | (-?)((\b\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)[ \t]*([+\-])[ \t]*((\b\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)([iI])|(-?)((\b\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)([iI])
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 | (-?)((\b\d+\.\d*|\.\d+)([eE][-+]?\d+)?)
432 |
433 |
434 |
435 |
436 |
437 | \b-?\d+\b
438 |
439 |
440 | \b\-?(?:\d+(?:\.\d*)?|(?:\.\d+))\b
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 | `
449 |
450 |
451 |
452 | `
453 |
454 |
455 |
456 |
457 | \\(?:'|"|n|r|t|b|f)
458 |
459 |
460 |
461 |
462 |
463 | "
464 |
465 |
466 |
467 | "|(?:(?<!\\)$)
468 |
469 |
470 |
471 |
472 | \\(?:\\|"|n|r|t|b|f)
473 |
474 |
475 |
476 |
477 |
478 | '
479 |
480 |
481 |
482 | '|(?:(?<!\\)$)
483 |
484 |
485 |
486 |
487 | \\(?:\\|'|n|r|t|b|f)
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 | (?i)(?<=[=(,:\+~!?\[|]|return|;|=>)\s*\/(?![\/*+{}?\r\n])
496 |
497 |
498 | \/([cgimosuxy]+\b)?
499 |
500 |
501 |
502 | \\(?:\/)
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 | (\b\s+([A-Za-zÀ-ÖØ-öø-ÿ0-9_\[\]]*))
512 |
513 | bool
514 | byte
515 | complex64
516 | complex128
517 | float32
518 | float64
519 | int
520 | int8
521 | int16
522 | int32
523 | int64
524 | rune
525 | string
526 | uint
527 | uint8
528 | uint16
529 | uint32
530 | uint64
531 | uintptr
532 |
533 |
534 |
535 |
536 | \b\s+(\*?)(\[\d*\])?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_\.]*)
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 | \b(import)\s*(\()?
550 |
551 |
552 |
553 |
554 | (\()?
555 |
556 |
557 | \s+([a-zA-ZÀ-ÖØ-öø-ÿ_]?[A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)[ \t]+"([a-zA-ZÀ-ÖØ-öø-ÿ_\.][A-Za-zÀ-ÖØ-öø-ÿ0-9-_\.\/]+)"
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 | append
567 | cap
568 | close
569 | complex
570 | copy
571 | delete
572 | imag
573 | len
574 | make
575 | new
576 | panic
577 | print
578 | println
579 | real
580 | recover
581 | Alignof
582 | Offsetof
583 | Sizeof
584 |
585 |
586 |
587 |
588 | _
589 |
590 |
591 |
592 |
593 |
594 | adler32
595 | aes
596 | ascii85
597 | asn1
598 | ast
599 | base64
600 | big
601 | bignum
602 | binary
603 | block
604 | bufio
605 | bytes
606 | crc32
607 | datafmt
608 | doc
609 | dwarf
610 | ebnf
611 | elf
612 | eval
613 | exec
614 | expvar
615 | flag
616 | flate
617 | fmt
618 | git85
619 | gob
620 | gosym
621 | gzip
622 | hash
623 | heap
624 | hex
625 | hmac
626 | http
627 | image
628 | io
629 | iotest
630 | iterable
631 | json
632 | list
633 | log
634 | macho
635 | malloc
636 | math
637 | md5
638 | net
639 | once
640 | os
641 | parser
642 | patch
643 | path
644 | pem
645 | png
646 | printer
647 | proc
648 | quick
649 | rand
650 | rc4
651 | reflect
652 | regexp
653 | ring
654 | rpc
655 | rsa
656 | runtime
657 | scanner
658 | script
659 | sha1
660 | sort
661 | stdio
662 | strconv
663 | strings
664 | subtle
665 | sync
666 | syscall
667 | tabwriter
668 | tar
669 | template
670 | testing
671 | time
672 | tls
673 | token
674 | unicode
675 | unsafe
676 | utf8
677 | vector
678 | x509
679 | xml
680 | zlib
681 |
682 |
683 |
684 |
685 | (\.)([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)(?=\()\b
686 |
687 |
688 |
689 |
690 |
691 | \b(?<!\.)([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)(?=\()\b
692 |
693 |
694 |
695 | \b[A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*\b
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 | \{
706 |
707 |
708 |
709 |
710 |
711 | \}
712 |
713 |
714 | [\(\[\)\]]
715 |
716 |
717 | (\+|\-|\*|\/|%|\+\+|\-\-|:\=|\=|\=\=|!\=|\+\=|\-\=|\*\=|\/\=|%\=|\<|\>|\<\=|\<\-|\>=|\=\=\=|!\=\=|&&|\||\|\||!|\^|&|\<\<|\>\>|~|\.\.\.)
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 | \.
726 |
727 |
728 | \(
729 |
730 |
731 | \)
732 |
733 |
734 | (\()|(\)(?:;|(,))?)
735 |
736 |
737 |
738 |
739 |
740 | \?
741 |
742 |
743 | \;
744 |
745 |
746 |
747 |
748 |
749 | ,
750 |
751 |
752 |
753 | (\{)|(\}(?:;|(,))?)|(\[)|(\](?:;|(,))?)
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 | :
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 | (([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)\s*(:))
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 | ((?:(var)\s+)?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)\s*(:?\=))(?!=)
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 | ((?:(const)\s+)?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)\s*(:?\=))(?!=)
789 |
790 |
791 |
792 |
793 |
794 |
795 | (([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$.]+)\s*(:?\=))(?!\=)
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 | (\.)([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)\s*(\()
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 | \b[var|const]\b
817 |
818 |
819 | \(
820 |
821 |
822 |
823 | \)
824 |
825 |
826 |
827 |
828 | (?=\b(?:func|if|else|while|for)\b)
829 |
830 |
831 |
832 | ,
833 |
834 |
835 |
836 |
837 | (?<!\=)\b([a-zØ-ö_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+(\*?)(\[\d*\])?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 | (?<!\=)\b([A-ZÀ-ÖØ-ö_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\s+(\*?)(\[\d*\])?([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_]*)\b
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
857 |
858 |
860 |
861 | ([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)\s*(\()
862 |
863 |
864 |
865 |
866 |
867 | ([A-Za-zÀ-ÖØ-öø-ÿ_][A-Za-zÀ-ÖØ-öø-ÿ0-9_][\w$]*)
868 |
869 |
870 |
871 |
872 |
873 |
--------------------------------------------------------------------------------